javascript - binding multi dropdown list in knockout.js -


i have multi dropdown list , need following:
1. make sure when selecting value in 1 dropdown list won't appear in others (couldn't find proper solution here).
2. when selecting value "text" text field (<input>) apear instead of yes/no dropdown.
3. "choose option" appear first row (still working on it).
4. make sure if "text" selected, on top (still working on it).

jsfiddle

html:

  <div class='liveexample'>     <table width='100%'>                 <tbody data-bind='foreach: lines'>                     <tr>                         <td>                             choose option:                         </td>                         <td>                             <select data-bind='options: filters, optionstext: "name", value: filtervalue'> </select>                         </td>                         <td data-bind="with: filtervalue">                             <select data-bind='options: filtervalues, optionstext: "name", value: "name"'> </select>                         </td>                         <td>                             <button href='#' data-bind='click: $parent.removefilter'>remove</button>                         </td>                     </tr>                 </tbody>             </table>             <button data-bind='click: addfilter'>add choice</button> 

javascript:

var cartline = function() {     var self = this;     self.filter = ko.observable();     self.filtervalue = ko.observable();      // whenever filter changes, reset value selection     self.filter.subscribe(function() {         self.filtervalue(undefined);     }); };  var cart = function() {     // stores array of filters     var self = this;     self.lines = ko.observablearray([new cartline()]); // put 1 line in default      // operations     self.addfilter = function() { self.lines.push(new cartline()) };     self.removefilter = function(line) { self.lines.remove(line) }; };   ko.applybindings(new cart()); 

i appeaciate assist here! first problem.

thanks!
mike

if want limit options based on options selected in ui, you'll need make sure every cartline gets own array of filters. let's pass in constructor so:

var cartline = function(availablefilters) {   var self = this;   self.availablefilters = availablefilters;    // other code   // ... }; 

you'll have use new viewmodel property instead of global filters array:

<td>   <select data-bind='options: availablefilters,      optionstext: "name",      value: filtervalue'> </select> </td> 

now, we'll have find out filters still available when creating new cartline instance. cart manages lines, , has addfilter function.

self.addfilter = function() {   var availablefilters = filters.filter(function(filter) {     return !self.lines().some(function(cartline) {       var currentfiltervalue = cartline.filtervalue();       return currentfiltervalue &&         currentfiltervalue.name === filter.name;     });   });    self.lines.push(new cartline(availablefilters)) }; 

the new cartline instance gets filter aren't yet used in other line. (note: if want use array.prototype.some in older browsers, might need polyfill)

the thing remains more of ux decision "coding decision": want users able change previous "choices" after having added new one? if case, you'll need create computed availablefilters arrays rather ordinary ones.

here's forked fiddle contains code posted above: http://jsfiddle.net/ztwcql69/ note can create doubled choices, because choices remain editable after adding new ones. if comment desired behavior be, can figure out how so. might require more drastic changes... solution provided more of pointer in right direction.

edit: felt bad not offering final solution, here's approach:

if want update availablefilters retrospectively, can this:

cartlines reference siblings (the other cart lines) , create subscription changes via ko.computed uses siblings and filtervalue:

var cartline = function(siblings) {   var self = this;    self.availablefilters = ko.computed(function() {     return filters.filter(function(filter) {       return !siblings()         .filter(function(cartline) { return cartline !== self })         .some(function(cartline) {         var currentfiltervalue = cartline.filtervalue();         return currentfiltervalue &&           currentfiltervalue.name === filter.name;       });     });   });    // other code... }; 

create new cart lines so: self.lines.push(new cartline(self.lines)). initiate empty array , push first cartline afterwards using addfilter.

concerning point 2: can create computed observable sorts based on filtervalue:

self.sortedlines = ko.computed(function() {    return self.lines().sort(function(linea, lineb) {     if (linea.filtervalue() && linea.filtervalue().name === "text") return -1;     if (lineb.filtervalue() && lineb.filtervalue().name === "text") return 1;      return 0;   });  }); 

point 3: move outside foreach.

point 4: use if binding:

<td data-bind="with: filtervalue">   <!-- ko if: name === "text" -->   <input type="text">   <!-- /ko -->   <!-- ko ifnot: name === "text" -->   <select data-bind='options: filtervalues, optionstext: "name", value: "name"'> </select>              <!-- /ko --> <td> 

updated fiddle contains code: http://jsfiddle.net/z22m1798/


Comments

Popular posts from this blog

javascript - Laravel datatable invalid JSON response -

java - Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; -

sql server 2008 - My Sql Code Get An Error Of Msg 245, Level 16, State 1, Line 1 Conversion failed when converting the varchar value '8:45 AM' to data type int -