knockout and Select2 get selected object
Asked Answered
I

3

7

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

Illconditioned answered 17/2, 2014 at 23:0 Comment(0)
D
8

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

    }
});
Drayage answered 18/2, 2014 at 2:36 Comment(3)
I tried this suggestion, but I do not see a property named data in the choice property.Peccable
The brace was in the wrong place. Edited the answer to make sure the data property is set correctlyHebner
Alan, your edit was rejected, but it was correct. I have fixed the code... thanks.Drayage
D
5

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/

Divulgence answered 17/7, 2016 at 4:13 Comment(0)
C
0

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')
})
Cundiff answered 29/11, 2017 at 13:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.