trajce trajce - 4 months ago 103
jQuery Question

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

Answer

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

    }
});
Comments