Saturday, 15 May 2010

jquery - KnockoutJS custom binding to get comma separated values from multi select -



jquery - KnockoutJS custom binding to get comma separated values from multi select -

i having next select in html:

<select class="form-control" data-bind="multiselectcommaseparated: cityids, options: $root.cities, optionstext: 'cityname', optionsvalue: 'cityid', valueupdate: 'change'" multiple="true"></select>

i trying write knockout custom binding update cityids observable comma separated values whenever user selects multiple cities in multi select drop down. illustration if have next select:

<select id="cities" multiple="multiple"> <option value="1">city 1</option> <option value="2">city 2</option> <option value="3">city 3</option> <option value="4">city 4</option> </select>

and user selects first 3 cities, observable should have 1,2,3. if user de-selects city 3, observable should have 1,2 , should happen shortly user selects/de-selects value in select.

i have written next custom binding using reference this question:

ko.bindinghandlers.multiselectcommaseparated = { init: function (element, valueaccessor) { var selmulti = $.map($(element.id + " option:selected"), function (el, i) { homecoming $(el).text(); }); valueaccessor(selmulti); }, update: function (element, valueaccessor) { var selmulti = $.map($(element.id + " option:selected"), function (el, i) { homecoming $(el).text(); }); valueaccessor(selmulti); } }

in above custom binding, update event not firing when alter selection in multi select dropdown. should alter in custom binding accomplish requirement?

i'm not quite straight up answering question, else (or i) may in separate answer. instead, allow me propose alternative way handle this, imho improve suited knockout's mvvm style.

construct view model hold csv string want computed observable. example:

var viewmodel = function() { var self = this; self.cities = [ {cityid: 1, cityname: "city 1"}, {cityid: 2, cityname: "city 2"}, {cityid: 3, cityname: "city 3"}, {cityid: 4, cityname: "city 4"} ]; self.selectedcities = ko.observablearray([]); self.selectedcitiescsv = ko.computed(function(){ homecoming self.selectedcities().join(","); }); };

you can test this view:

class="lang-html prettyprint-override"><select class="form-control" data-bind="selectedoptions: selectedcities, options: $root.cities, optionstext: 'cityname', optionsvalue: 'cityid', valueupdate: 'change'" multiple="true"></select> <hr /> csv: <p data-bind="text: selectedcitiescsv"></p>

see this fiddle demo.

the advantages of approach on custom binding include:

unit testable; no custom bindings needed; knockout keeps our csv string in synch view, no custom code needed; no dependency on jquery needed, if possible leverage ko maintain js ignorant of actual dom (which 1 time again improves testability);

in case you're not using constructor functions viewmodels, plain javascript objects, have add together computed observables after creating object base of operations properties. this:

var viewmodel = { cities :[ {cityid: 1, cityname: "city 1"}, {cityid: 2, cityname: "city 2"}, {cityid: 3, cityname: "city 3"}, {cityid: 4, cityname: "city 4"} ], selectedcities : ko.observablearray([]) }; viewmodel.selectedcitiescsv = ko.computed(function(){ homecoming viewmodel.selectedcities().join(","); });

or see this modified fiddle.

jquery knockout.js

No comments:

Post a Comment