Vue ajax search component

So as i was on my journey learning and creating www.worknxt.com, i needed a Vue component that:
  • when user type it goes and call an end point.
  • replace part of the URL with search text.
  • coming back with results, user can select one but then the value that go up to parent is like and Id value of selected item while keep the display text of the component on another value.
  • everything should be assigned through props so this can be reused.
i googled but couldn't find any free Vue component that accomplish this and satisfy my requirements.
below code is what i ended up with, let me know what you think, it needs some work on responding to keyboard keys like down arrow but i think it's a good start, so i though to share.


Vue.component('vue-autocompleteajax', {
    props: {
        placeHolderText: String,
        minLengthToSearch: { type: Number, default: 1 },
        ajaxUrl: String,
        partToReplace: String,
        idProperty: String,
        textProperty: String,
        value: String
    },

    data() {
        return {
            keywordSearch: '',
            resultItems: [],
            autoCompleteProgress: false,
            lastValue: '',
            lastId: ''
        }
    },
    methods: {
        onKeyUp: function (keywordEntered) {
            this.resultItems = [];
            this.autoCompleteProgress = false;
            if (keywordEntered.length > this.$props.minLengthToSearch) {
                this.autoCompleteProgress = true;
                var self = this;
                var link = this.$props.ajaxUrl;

                link = link.replace(this.$props.partToReplace, keywordEntered);
                $.ajax({
                    url: link,
                    method: "GET",
                    success: function (data) {
                        var newResult = [];
                        data.forEach(function (item, index) {
                            newResult.push({ itemId: item[self.$props.idProperty], itemText: item[self.$props.textProperty] });
                        });
                        self.resultItems.push(...newResult);
                        self.autoCompleteProgress = false;
                    }
                });

                
            }
        },
        onSelected: function (Id, displayText) {
            this.autoCompleteProgress = false;
            this.keywordSearch = displayText;
            this.lastValue = displayText;
            this.lastId = Id;
            this.resultItems.splice(0, this.resultItems.length);
            this.$refs.searchInput.focus();
            this.$emit('input', Id);
        },
        onLostFocus: function () {
            var self = this;
            setTimeout(function () {
                var matchedItem = self.resultItems.find(item => item['itemText'] === self.keywordSearch);
                if (typeof matchedItem !== 'undefined') {
                    self.lastValue = self.keywordSearch;
                    self.lastId = matchedItem['itemId'];
                    self.$emit('input', self.lastId);
                } else {
                    self.keywordSearch = self.lastValue;
                }
                self.resultItems.splice(0, self.resultItems.length);
            }, 200);
        }
    },
    template: `<div>
    	<input ref="searchInput" type="text" class="form-control" :placeholder="placeHolderText" v-model="keywordSearch" @keyup="!autoCompleteProgress ? onKeyUp(keywordSearch) : ''" @blur="onLostFocus"/>
        <ul v-if="resultItems.length > 0" class="list-group" style="position: absolute; z-index: 99; width: 100%; display: block;">
        	<li style="cursor: default;" v-for="resultItem in resultItems" v-bind:key="resultItem.itemId" @click="keywordSearch='';onSelected(resultItem.itemId, resultItem.itemText)" class="list-group-item">{{ resultItem.itemText }}</li>
        </ul>
</div>`
});

Popular posts from this blog

add extra files on deploy ASP Core web app using publish profile

how to copy NuGet packages from one project to another

S/MIME Certificate and GMail