3

So i have a select2 tag input working fine, displaying the tags correctly, and storing the selected id into the selectedProducts observableArray. However, my HTTPPost is expecting an array of objects, and not an array of integers. I've been looking to see how I can have the select2 save as an object (i.e. {id: 1, text: "abc"}) instead of just an array of integers.

My binding is below:

<div class="col-sm-10">
    <input type="hidden" id="tags" class="select2 form-control" multiple="multiple" data-bind="value: selectedProducts, select2: {tags: ko.toJS($parent.availableProducts), placeholder: 'select products'}" />
    <pre data-bind="text: ko.toJSON(products, null, 2)"></pre>   
</div>           

var newItem = function (newitem) {
    var self = this;

    self.id = ko.observable();  
    self.selectedProducts = ko.observableArray();
    self.products = ko.computed(function () {
        return self.selectedProducts().split(',');
    }, self);
}       

var viewModel = function (data) {
    var self = this;
    self.newitem= ko.observable(new newItem());    
    self.availableProducts = ko.observableArray([]);      
    $.ajax({
        type: "GET",
        url: '/GetAllProducts',
        dataType: 'json',
        contentType: "application/json; charset=utf-8",
        async: false,
        success: function (data) {
            ko.mapping.fromJS(data, {}, self.availableProducts);
        },
        error: function (err) {
            alert(err.status + " : " + err.statusText);
        }
    });       
}
ko.bindingHandlers.select2 = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var obj = valueAccessor(),
          allBindings = allBindingsAccessor(),
          lookupKey = allBindings.lookupKey;

        setTimeout(function () {
            $(element).select2(obj);
        }, 0);

        if (lookupKey) {
            var value = ko.utils.unwrapObservable(allBindings.value);
            $(element).select2('data', ko.utils.arrayFirst(obj.data.results, function (item) {
                return item[lookupKey] === value;
            }));
        }

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).select2('destroy');
        });
    },
    update: function (element) {
        $(element).trigger('change');
    }
}
chickenricekid
  • 390
  • 4
  • 19

1 Answers1

3

select2 is wrapping a form field so you can't directly post a JSON object. It may be easiest to modify the server side code to work with IDs if you can.

If not you could use the id parameter in the select2 constructor, and return a stringified JSON object you parse on the server. For example (untested) in your data-bind:

select2: {
    tags: ko.toJS($parent.availableProducts),
    placeholder: 'select products',
    id: function(product) { return JSON.stringify({server_id: product.id, server_text: product.text}) }
}

More info on this approach:

POST data in JSON format https://github.com/ivaynberg/select2/issues/852#issuecomment-13478644

Maybe In the future we'll have JSON form submission.

Community
  • 1
  • 1
thebenedict
  • 2,539
  • 3
  • 20
  • 29
  • Makes sense - It sounds like it'll be much easiser to just make my server side code user the IDs. Thanks for that clarification – chickenricekid Dec 16 '14 at 17:03