javascript - KnockoutJS showing a sorted list by item category -


i started learning knockout week , has gone except 1 issue.

i have list of items sort multiple ways 1 of ways want sort needs have different display standard list. example lets have code

var betterlistmodel = function () { var self = this; food = [ {     "name":"apple",     "quantity":"3",     "category":"fruit",     "cost":"$1", },{     "name":"ice cream",     "quantity":"1",     "category":"dairy",     "cost":"$6", },{     "name":"pear",     "quantity":"2",     "category":"fruit",     "cost":"$2", },{     "name":"beef",     "quantity":"1",     "category":"meat",     "cost":"$3", },{     "name":"milk",     "quantity":"5",     "category":"dairy",     "cost":"$4", }]; self.allitems = ko.observablearray(food); // initial items                                             // initial sort self.sortme = ko.observable("name"); ko.utils.compareitems = function (l, r) {     if (self.sortme() =="cost"){         return l.cost > r.cost ? 1 : -1      } else if (self.sortme() =="category"){         return l.category > r.category ? 1 : -1     } else if (self.sortme() =="quantity"){         return l.quantity > r.quantity ? 1 : -1     }else {         return l.name > r.name ? 1 : -1      }     }; }; ko.applybindings(new betterlistmodel()); 

and html

<p>your values:</p> <ul class="deckcontents" data-bind="foreach:allitems().sort(ko.utils.compareitems)">     <li><div style="width:100%"><div class="left" style="width:30px" data-bind="text:quantity"></div><div class="left fixedwidth" data-bind="text:name"></div> <div  class="left fixedwidth" data-bind="text:cost"></div> <div  class="left fixedwidth" data-bind="text:category"></div><div style="clear:both"></div></div></li> </ul> <select data-bind="value:sortme">     <option selected="selected" value="name">name</option>     <option value="cost">cost</option>     <option value="category">category</option>     <option value="quantity">quantity</option> </select> </div> 

so can sort these fine field might sort them name , display this

3 apple $1 fruit 1 beef $3 meat 1 ice cream $6 dairy 5 milk $4 dairy 2 pear $2 fruit 

here fiddle of have far http://jsfiddle.net/darksbane/x7kvb/

this display fine sorts except category sort. want when sort them category display this

fruit 3 apple $1 fruit 2 pear $2 fruit  meat 1 beef $3 meat  dairy 1 ice cream $6 dairy 5 milk $4 dairy 

does have idea how might able display differently 1 sort?

  • your view shouldn't contain logic beyond necessary render it. thus, foreach binding data-bind="foreach:allitems().sort(ko.utils.compareitems)" should become computed observable.

  • you should move <option> data model , take advantage of options data-bind.

to address actual question, you'll take advantage of template binding , containerless if binding.

the template binding allow change look/feel of view based on selected sort type. 2 templates available, default-template handles regular display , category-template category based rendering.

<script type="text/html" id="category-template">  <ul class="deckcontents" data-bind="foreach:sorteditems">      <li>          <!-- ko if: $root.outputcategory($index()) -->          <div data-bind="text:category"></div>          <!-- /ko -->           <span class="indented" data-bind="text:name"></span>            <span  class="indented" data-bind="text:cost"></span>            <span  class="indented" data-bind="text:category"></span>      </li>  </ul> 

the html usage: <div data-bind='template: { name: currenttemplate, data: $data}'></div> currenttemplate computed observable returns template id based on sort type.

in way or must assign priority categories. have done declaring var categorypriority = ["fruit", "meat", "dairy"].

have @ my fiddle. i didn't address fixedwidth used default-template you'll need handle css styling line way want.

edit: is there way dynamically add item list , have show in sorted list automatically?

  1. pushing new item: when want knockout "notify" other elements don't want read observablearray using allitems() before performing push. instead, you'll push observablearray using allitems.push in-turn cause knockout trigger computed observables (that depend on observable) evaluate, subscriptions execute, dom elements update ... etc.

  2. computed dependencies: in order computed "depend" on observable has read inside of provided evaluator function. since, sorteditems reads sorttype "trigger" re-evaluation. thus, changing allitems.sort allitems().sort causes sorteditems evaluate whenever changes made allitems.

see how dependency tracking works


Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

ios - Change Storyboard View using Seague -