<template> <div class="row form-group mt-3" :key="$attrs.key"> <label :for="localFormElement.key" :class="$attrs.labelClass ?? 'col-md-3'" >{{ localFormElement.label }}</label > <vue-tribute :options="tributeOptions" :class="[$attrs.inputClass ?? ' col-md-9', { error: hasError }]" class="mt-2" > <input @focus="clearErrors" @blur="validate" @input="$emit('oninput', $event)" @tribute-no-match="noMatchFound" @tribute-replaced="textReplaced" class="form-control tribute in-advanced-search" :placeholder="localFormElement.placeholder" :type="localFormElement.type" :id="localFormElement.key" :name="localFormElement.key" v-model="textValue" /> </vue-tribute> </div> </template> <script> import VueTribute from "vue-tribute"; import formBuilderMixin from "@mixins/formBuilderMixin"; export default { mixins: [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 mini tribute-component", // 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, }, }; }, methods: { remoteSearch(text, cb) { this.$emit("tribute-on-search", { text, cb, item: this.localFormElement, }); }, noMatchFound(args) { // console.info(args); }, textReplaced(args) { // console.info(args); }, }, components: { VueTribute: () => import( "vue-tribute"), }, }; </script> <style scoped lang="scss"></style>