I want to use Choices JS as the UI for server side search filtering. The demo only includes loading the whole list and filtering client-side – I have too many records for that to be viable.
I have got it working except for one thing, which is that as you type, the search box loses focus, meaning its almost unusable from a UX point of view.
I have this so far (note it is wrapped in a Knockout binding and uses a timeout as a fake request):
(function()
{
var _getConfig = function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)
{
var cfg = ko.unwrap(f_valueaccessor());
var res = {
obs: cfg.boundField,
src: cfg.src,
multiple: ko.unwrap(cfg.multiple) || false,
options: cfg.options || {},
_current: cfg.items || ko.observableArray()
};
return res;
};
ko.bindingHandlers.choices = {
init:
function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)
{
var cfg = _getConfig(el, f_valueaccessor, allbindings, viewmodel, bindingcontext);
cfg.multiple && el.setAttribute('multiple');
var chc = new Choices(el, {
searchChoices: false,
shouldSort: false,
shouldSortItems: false
});
chc.setChoices(function()
{
return cfg.src(chc, { initial: true, term: null });
});
el.addEventListener('search', function(e)
{
console.log('search', e);
chc.setChoices(function() { return cfg.src(chc, { initial: false, term: e.detail.value }) });
});
},
update:
function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)
{
}
};
})();
var model = new function()
{
this.Choice = ko.observableArray();
this.IsMultiple = ko.observable(false);
this.find = function(sender, eargs)
{
return new Promise(function(resolve)
{
setTimeout(function()
{
resolve([{ value: 1, label: 'Hello' }, { value: 2, label: 'World' }]);
}, 100);
});
};
};
ko.applyBindings(model);
Working Fiddle: https://jsfiddle.net/whelkaholism/5sn9wt0r/22/
UPDATE:
I have changed the search event handler to the below and it works, but it seems pretty hacky, is there a better way?
el.addEventListener('search', function(e)
{
console.log('search', e, chc);
chc.setChoices(function() {
return new Promise(function(resolve){
cfg.src(chc, { initial: false, term: e.detail.value }).then(function(data) {
resolve(data);
setTimeout(function() {chc.choiceList.element.parentElement.querySelector('input[type=search]').focus(); }, 0);
});
});
});
});