Search code examples
knockout.jsjquery-select2knockout-3.0

Knockout3+select2 (v4) with ajax


I'm trying to get select2 to work with knockout. My datasource is quite large, and therefor I want it to utilize AJAX. My code works perfectly when I'm not using AJAX.

ko.bindingHandlers.select2 = {
        init: (element, valueAccessor, allBindings) => {
            $(element).select2({
                // allowClear: false,
                ajax: {
                    url: '/api/person-catalog',
                    data: (params) => {
                        return {
                            name: params.term
                        };
                    },
                    dataType: 'json',
                    delay: 250,
                    processResults: (data, params) => {
                        $.each(data, (key, val) => {
                            data[key].text = val.nameDA;
                        });

                        return {
                            results: data
                        };
                    },
                    cache: true
                },
                placeholder: 'Enter name',
                escapeMarkup: function (markup) {
                    return markup;
                } // , // let our custom formatter work
                //minimumInputLength: 1,
                //templateResult: formatRepo,
                // templateSelection: formatRepoSelection
            });

            // hacky solution
            $(element).on('change', evt => {
                if ($(element).select2('data')[0] !== null && parseInt($(element).select2('data')[0]['id']) > 0){
                    const item = $(element).select2('data')[0];
                    allBindings().value(item['name']);
                }
            });
        },

        update: (el, valueAccessor, allBindingsAccessor, viewModel) => {
            const allBindings = allBindingsAccessor();
            $(el).trigger("change");
            $(el).val(allBindings.value()).trigger('change');
            console.log($(el).val());
        }
    };

and html:

<select data-bind="value: chosenValue, select2"></select>

I'm not able to use the "update" since it is not triggered when the value changes. What I optimally want is to be able to have a "value" set which is updated whenever the select2 is changed.

Please note that it exists in a table where a lot of select2 instances are created. Alternative solutions are also very welcome.

Regards


Solution

  • I found that messing with the value binding is not a good idea in this regard. Instead I use another binding (e.g. name) and remove everything in the update. The result is something like:

    ko.bindingHandlers.select2 = {
        init: (element, valueAccessor, allBindings) => {
            $(element).select2({
    
                ajax: {
                    url: '/api/person-catalog',
                    data: (params) => {
                        return {
                            name: params.term
                        };
                    },
                    dataType: 'json',
                    delay: 250,
                    processResults: (data, params) => {
                        $.each(data, (key, val) => {
                            data[key].text = val.name;
                        });
    
                        return {
                            results: data
                        };
                    },
                    cache: true
                }
            });
    
            $(element).on('change', evt => {
                if ($(element).select2('data')[0] !== null && parseInt($(element).select2('data')[0]['id']) > 0){
                    const item = $(element).select2('data')[0];
                    allBindings().name(item['name']);
                }
            });
        },
    
        update: (el, valueAccessor, allBindingsAccessor, viewModel) => {
    
        }
    };