Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 980
trajce Avatar asked Feb 17 '14 23:02

trajce


2 Answers

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

    }
});
like image 142
Robert Slaney Avatar answered Sep 20 '22 14:09

Robert Slaney


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/

like image 41
Seyeong Jeong Avatar answered Sep 19 '22 14:09

Seyeong Jeong