<template> <div class="d-flex"> <label :for="localFormElement.key" :class="$attrs.labelClass ?? 'col-md-3'">{{ localFormElement.label }}:</label> <div class="d-flex" :class="[$attrs.inputClass ?? ' col-md-9', { error: hasError }]"> <div class="col-md-5"> <multiselect class="class-search" track-by="id" label="title" placeholder=" انتخاب کنید... " v-model="templateValue" :options="options" :searchable="true" :internal-search="false" :clear-on-select="false" :close-on-select="true" :options-limit="300" :limit="3" :max-height="350" @search-change="asyncFind" @select="forwardMessage" @close="resetFoundUsers"> </multiselect> </div> <div class="d-flex col-md-10"> <vue-tribute class="col-md-12 ps-0 pe-0" :options="tributeOptions"> <input class="label-1 form-control task-form-control task-title" :placeholder="localFormElement.placeholder" :type="localFormElement.type" :id="localFormElement.key" :name="localFormElement.key" v-model="textValue" @tribute-no-match="noMatchFound" @tribute-replaced="textReplaced" /> </vue-tribute> <button type="button" class="btn btn-light button-input" :class="$attrs.buttonClass" @click.prevent="sendTextValue" style="width: 4em"> <svg class="icon icon-Component-233--1"> <use xlink:href="#icon-Component-233--1"></use> </svg> </button> </div> <button type="button" class="btn btn-light" v-if="isUpdateitem" @click="handlerUpdate"> <svg class="icon icon-Component-294--1"> <use xlink:href="#icon-Component-294--1"></use> </svg> </button> </div> </div> </template> <script> import formBuilderMixin from "@mixins/formBuilderMixin"; import HttpService from "@services/httpService"; import apis from "@apis/borhanApi.js"; import VueTribute from "vue-tribute"; import { mapGetters, mapMutations, mapActions } from "vuex"; export default { mixins: [formBuilderMixin], beforeMount() { this.httpService = new HttpService(); }, mounted() { this.multiSelectValue(this.formElement.key); }, data() { return { taskForm: "", httpService: undefined, templateValue: "", options: [ { title: "rational", name: "rational", }, { title: "real", name: "real", }, { title: "plainliteral", name: "plainliteral", }, { title: "xmlliteral", name: "xmlliteral", }, { title: "literal", name: "literal", }, { title: "anyuri", name: "anyuri", }, { title: "base64binary", name: "base64binary", }, { title: "double", name: "double", }, { title: "byte", name: "byte", }, { title: "datetime", name: "datetime", }, { title: "datetimestamp", name: "datetimestamp", }, { title: "decimal", name: "decimal", }, { title: "float", name: "float", }, { title: "hexbinary", name: "hexbinary", }, { title: "int", name: "int", }, { title: "integer", name: "integer", }, { title: "language", name: "language", }, { title: "long", name: "long", }, { title: "name", name: "name", }, { title: "ncname", name: "ncname", }, { title: "negativeinteger", name: "negativeinteger", }, { title: "nmtoken", name: "nmtoken", }, { title: "nonnegativeinteger", name: "nonnegativeinteger", }, { title: "nonpositiveinteger", name: "nonpositiveinteger", }, { title: "normalizedstring", name: "normalizedstring", }, { title: "positiveinteger", name: "positiveinteger", }, { title: "short", name: "short", }, { title: "string", name: "string", }, { title: "token", name: "token", }, { title: "unsignedbyte", name: "unsignedbyte", }, { title: "unsignedint", name: "unsignedint", }, { title: "unsignedlong", name: "unsignedlong", }, { title: "unsignedshort", name: "unsignedshort", }, ], 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 mini", // 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.title; // return "@" + item.original.value; }, // template for displaying item in menu menuItemTemplate: function (item) { return item.original.title; }, // 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: "title", // column that contains the content to insert by default fillAttr: "title", // REQUIRED: array of objects to match or a function that returns data (see 'Loading remote data' for an example) // values: [ // { // key: null, // value: "sghl", // }, // ], // 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 style="color:red">', 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, }, }; }, computed: { ...mapGetters("borhan", ["ontologyIdGetter", "clickPointNameGetter"]), }, methods: { asyncFind() { }, multiSelectValue(item) { if (item == "objcet_property_assertions") { this.httpService .getRequest( apis.property.update + "?ontology_id=" + this.ontologyIdGetter + `&name1=${"objectproperty"}` ) .then((res) => { const list = res.data.Subobject_property; const processedList = []; list.forEach((element) => { const newItem = { title: element.title, name: element.title }; // ایجاد یک شیء جدید با ویژگی title processedList.push(newItem); // اضافه کردن شیء جدید به لیست }); this.options = processedList; }); } }, forwardMessage(newTag) { this.templateValue = newTag; }, resetFoundUsers() { }, noMatchFound(args) { console.info(args); }, textReplaced(args) { console.info(args); }, remoteSearch(text, cb) { let url = ""; if (this.formElement.key == "type") { const queryParams = new URLSearchParams({ ontology_id: this.ontologyIdGetter, search: text, }); url = apis.class.autoComplate + "?" + queryParams; } else { const queryParams = new URLSearchParams({ ontology_id: this.ontologyIdGetter, search: text, }); url = apis[this.$route.name].autoComplate + "?" + queryParams; } // if (text == "") url = taskApi.workingHours.complitionAll; this.httpService .getRequest(url) .then((response) => { const list = response.data; const processedList = []; list.forEach((element) => { const newItem = { title: element }; // ایجاد یک شیء جدید با ویژگی title processedList.push(newItem); // اضافه کردن شیء جدید به لیست }); cb(processedList); }) .catch((error) => { }) .finally(() => { }); }, sendTextValue() { this.$emit("keydown", { text: this.textValue, prop: this.templateValue.name, key: this.keyValue, isUpdate: this.isUpdateitem, }); this.textValue = ""; }, handlerUpdate() { this.textValue = ""; this.templateValue = ""; this.isUpdateitem = false; }, }, components: { VueTribute: () => import( "vue-tribute"), Multiselect: () => import( "vue-multiselect"), }, }; </script> <style scoped lang="scss"> .form-control { position: relative !important; } .button-input { background-color: unset !important; position: absolute !important; left: 2px !important; height: 100% !important; border: 0; display: flex; justify-content: flex-end; align-items: center; } </style> <style lang="scss"> .class-search { .multiselect__tags { border: unset; input { border: unset !important; } } } </style>