<template> <div class="row form-group mt-3" :key="$attrs.key"> <template v-if="enableSuggestion"> <label :for="localFormElement.key" :class="$attrs.labelClass ?? 'col-md-2'" >{{ localFormElement.label }}:</label > <!-- <vue-tribute :class="[$attrs.inputClass ?? ' col-md-10']" :options="tributeOptions" > --> <textarea @tribute-no-match="noMatchFound" @tribute-replaced="textReplaced" :ref="localFormElement.key" class="form-control" @focus="clearErrors" @blur="validate" @change="validate" :placeholder="localFormElement.placeholder" :id="localFormElement.key" :name="localFormElement.key" v-model="textValue" cols="30" :rows="getRows()" > </textarea> <!-- </vue-tribute> --> <context-menu style="position: static; display: inline-flex" v-if="contextMenu.length" :id="'context-menu-' + localFormElement.key" :contextMenu="contextMenu" @other="methodName($event)" > </context-menu> </template> <template v-else> <label :for="localFormElement.key" :class="$attrs.labelClass ?? 'col-md-3'" >{{ localFormElement.label }}:</label > <div class="mt-2" :class="[$attrs.inputClass ?? ' col-md-9']"> <textarea @tribute-no-match="noMatchFound" @tribute-replaced="textReplaced" :ref="localFormElement.key" class="form-control" @focus="clearErrors" @blur="validate" @change="validate" :placeholder="localFormElement.placeholder" :id="localFormElement.key" :name="localFormElement.key" v-model="textValue" cols="30" :rows="getRows()" > </textarea> </div> </template> </div> </template> <script> import formBuilderMixin from "~/extensions/formBuilderExtension.js"; // import VueTribute from "vue-tribute"; import apis from "~/apis/borhanApi.js"; export default { props: { enableSuggestion: { default: false, }, contextMenu: { default() { return []; }, }, }, extends: formBuilderMixin, data() { return { // tributeOptions: { // // symbol or string that starts the lookup // trigger: "", // // element to target for @mentions // iframe: null, // // class added in the flyout menu for active item // selectClass: "highlight", // // class added to the menu container // containerClass: "tribute-container", // // class added to each list item // itemClass: "my-tribute-class", // // function called on select that returns the content to insert // selectTemplate: function (item) { // return item.original.value; // // return "@" + item.original.value; // }, // // template for displaying item in menu // menuItemTemplate: function (item) { // return item.string; // }, // // template for when no match is found (optional), // // If no template is provided, menu is hidden. // noMatchTemplate: // '<span class="no-result">مورد مشابهی ثبت نشده است.</span>', // // specify an alternative parent container for the menu // // container must be a positioned element for the menu to appear correctly ie. `position: relative;` // // default container is the body // menuContainer: document.body, // // column to search against in the object (accepts function or string) // lookup: "key", // // column that contains the content to insert by default // fillAttr: "value", // // REQUIRED: array of objects to match or a function that returns data (see 'Loading remote data' for an example) // values: [ // { // key: "سلام", // value: "سلام", // }, // { // key: "باسلام", // value: "باسلام", // }, // { // key: "علیک سلام", // value: "علیک سلام", // }, // { // key: "بی سلام", // value: "بی سلام", // }, // { // key: "صدتا سلام", // value: "صدتا سلام", // }, // ], // // values: ["سلام", "باسلام", "علیک سلام", "بی سلام", "صدتا سلام"], // // values: (text, cb) => { // // this.remoteSearch(text, (items) => cb(items)); // // }, // // When your values function is async, an optional loading template to show // loadingItemTemplate: null, // // specify whether a space is required before the trigger string // requireLeadingSpace: true, // // specify whether a space is allowed in the middle of mentions // allowSpaces: true, // // optionally specify a custom suffix for the replace text // // (defaults to empty space if undefined) // // replaceTextSuffix: "", // // specify whether the menu should be positioned. Set to false and use in conjuction with menuContainer to create an inline menu // // (defaults to true) // positionMenu: true, // // when the spacebar is hit, select the current match // spaceSelectsMatch: false, // // turn tribute into an autocomplete // autocompleteMode: true, // // Customize the elements used to wrap matched strings within the results list // // defaults to <span></span> if undefined // searchOpts: { // pre: "<span>", // post: "</span>", // skip: false, // true will skip local search, useful if doing server-side search // }, // // Limits the number of items in the menu // menuItemLimit: 25, // // specify the minimum number of characters that must be typed before menu appears // menuShowMinLength: 0, // }, httpService: undefined, }; }, beforeMount() { this.httpService = useNuxtApp()["$http"]; }, mounted() {}, methods: { getRows() { if (this.localFormElement?.rows) return this.localFormElement?.rows; return "3"; }, noMatchFound(args) { console.info(args); }, textReplaced(args) { console.info(args); }, methodName(action, index = 0) { try { this[action](index); } catch (err) { this.$emit(action, index); } }, remoteSearch(input, callback) { console.info(input); return this.httpService .getRequest(apis.concept.annotations.read + "?ontology_id=" + input) .then((res) => { callback(res.data); }) .catch((e) => { callback([]); }) .finally(() => { this.fetchingData = false; }); }, }, components: { // VueTribute, }, }; </script> <style scoped> .form-control { height: auto !important; } </style> <style> .tribute-container { position: absolute; top: 0; left: 0; height: auto; overflow: auto; max-height: 25em; overflow: auto; display: block; z-index: 999999; transform: translate(-80px, 7px); box-shadow: 0 9px 8px -3px rgba(64, 60, 67, 0.24), 8px 0 8px -7px rgba(64, 60, 67, 0.24), -8px 0 8px -7px rgba(64, 60, 67, 0.24); box-shadow: 0px 0px 14px 0px #eee; border-radius: 0.3em; background: #ededed; } .tribute-container ul { margin: 0; margin-top: 2px; padding: 0; list-style: none; /* background: #efefef; */ } .tribute-container li { padding: 0.5em 1em; cursor: pointer; } .tribute-container li.highlight { /* background: #ddd; */ } .tribute-container li span { font-weight: bold; } .tribute-container li.no-match { cursor: default; } .tribute-container .menu-highlighted { font-weight: bold; } </style>