简体   繁体   中英

knockout and Select2 get selected object

I'm working on a project where im using .net web api, knockout and in this example, the jquery plugin select2 .

What im trying to do is to set some field values after the change of the selection. The select2 control list is loaded after ajax call and the objects contain more data than just id and text. How can i get the rest of the data, so i can fill the other inputs with it? Shortly, im trying to update a viewmodel after the change of the selection (but i get the data when this plugin makes the ajax call).

Here is a sample data that the selected object should contain:

{
   "Customer":{
      "ID":13,
      "No":"0000012",
      "Name":"SomeName",
      "Address":"SomeAddress",
      "ZipCode":"324231",
      "City":"SimCity",
      "Region":"SS",
      "Phone":"458447478",
      "CustomerLocations":[]
   }
}

Here is where i am for now:

Sample html:

<input type="hidden" data-bind="select2: { optionsText: 'Name', optionsValue: 'ID', sourceUrl: apiUrls.customer, model: $root.customer() }, value: CustomerID" id="CustomerName" name="CustomerName" />
<input type="text" data-bind="........" />
<input type="text" data-bind="........" /> 
etc...

and this is the custom binding:

ko.bindingHandlers.select2 = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var obj = valueAccessor(),
            allBindings = allBindingsAccessor();

        var optionsText = ko.utils.unwrapObservable(obj.optionsText);
        var optionsValue = ko.utils.unwrapObservable(obj.optionsValue);
        var sourceUrl = ko.utils.unwrapObservable(obj.sourceUrl);
        var selectedID = ko.utils.unwrapObservable(allBindings.value);
        var model = ko.utils.unwrapObservable(obj.model);//the object that i need to get/set

        $(element).select2({
            placeholder: "Choose...",
            minimumInputLength: 3,
            initSelection: function (element, callback) {
                if (model && selectedID !== "") {
                    callback({ id: model[optionsValue](), text: model[optionsText]() });
                }
            },
            ajax: {
                quietMillis: 500,
                url: sourceUrl,
                dataType: 'json',
                data: function (search, page) {
                    return {
                        page: page,
                        search: search
                    };
                },
                results: function (data) {
                    var result = [];
                    $.each( data.list, function( key, value ) {
                        result.push({ id: value[optionsValue], text: value[optionsText] });
                    });
                    var more = data.paging.currentPage < data.paging.pageCount;
                    return { results: result, more: more };
                }
            }
        });

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).select2('destroy');
        });
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var obj = valueAccessor(),
            allBindings = allBindingsAccessor();

        var model = ko.utils.unwrapObservable(obj.model);//the object that i need to get/set
        var selectedID = ko.utils.unwrapObservable(allBindings.value);

        $(element).select2('val', selectedID);

        $(element).on("change", function (e) {
            //...
        });
    }
};

Getting the selected id or text is not a problem, but how not to loose the rest of the information after the ajax call? Where can i set/get this object so i can have all the data that it contains?

Thank you

When you build a object literal for your results, added the full object as a "data" property.

result.push({ id: value[optionsValue], text: value[optionsText], data: value });

Then handle the select2-selected event thrown by select2. The event object this should contain your object literal as the choice property.

$element.on('select2-selected', function(eventData) {
    if ( eventData.choice ) {
        // item selected
        var dataObj = eventData.choice.data;
        var selectedId = eventData.choice.id;
    } else {
        // item cleared

    }
});

For select2 v4, you can use $(elem).select2('data') to get the selected objects.

$('selected2-enabled-elements').on('change', function(e) {
    console.log($(this).select2('data'));
});

Example: https://jsfiddle.net/calvin/p1nzrxuy/

For select2 versions before v4.0.0 you can do:

.on("select2-selecting", function (e) {
    console.log(e.object);
})

From v4.0.0 on and upwards the following should work:

.on("select2-selecting", function (e) {
    $(this).select2('data')
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM