riophae / vue-treeselect

A multi-select component with nested options support for Vue.js
https://vue-treeselect.js.org/
MIT License
2.91k stars 509 forks source link

Diacritic insensitive search #439

Closed Glideh closed 3 years ago

Glideh commented 3 years ago

I saw the search is already case insensitive, I'd like to know how can we ignore accents and other diacritics in searches.

I'm guessing we would have to use search-change event but I don't see how to use it.

Example with this data:

options: [
    { id: 1, label: 'màçhin' },
    { id: 2, label: 'chouétte' },
    { id: 3, label: 'trûc' },
]

If I type "machin" I need to see the "màçhin" option. If I type "chouette" I need to see the "chouétte" option.

I know we can remove diacritics like that

function removeDiacritics(text) {
    return text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}

But how can I pass it to treeselect ?

Glideh commented 3 years ago

I found a way to work around the issue by using the async feature.

<treeselect
  :options="items"
  :async="true"
  :load-options="searchItems"
  :default-options="true"
>
</treeselect>

async will call searchItem whenever something has been entered in the search default-options will also call searchItems when opening the select before anything is typed

function removeDiacritics(text) {
    return text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}
function normalizedContains(needle, haystack) {
    const regExp = new RegExp(removeDiacritics(needle), 'gi');
    return regExp.test(removeDiacritics(haystack));
}

export default {
// ...
    methods:
// ...
        searchItems({ searchQuery, callback }) {
            const itemsFiltered = searchQuery
                ? this.items.filter(item => normalizedContains(searchQuery, item))
                : this.items;
            callback(null, itemsFiltered);
        }

callback must be called with the itemsFiltered so the result gets displayed in the select.

If someone has a better way, don't hesitate to share.