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
bindingdata-bind="foreach:allitems().sort(ko.utils.compareitems)"
should becomecomputed
observable.you should move
<option>
data model , take advantage ofoptions
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?
pushing new item: when want knockout "notify" other elements don't want
read
observablearray usingallitems()
before performing push. instead, you'll push observablearray usingallitems.push
in-turn cause knockout triggercomputed observables
(that depend on observable) evaluate,subscriptions
execute, dom elements update ... etc.computed dependencies: in order computed "depend" on observable has
read
inside of provided evaluator function. since,sorteditems
readssorttype
"trigger" re-evaluation. thus, changingallitems.sort
allitems().sort
causessorteditems
evaluate whenever changes madeallitems
.
Comments
Post a Comment