I have an some dynamic data loaded in to an array named "tabNames" like this:
tabNames.push({name: hit.category});
Then I need to list the "name" fields in the following html. I want to list first 7 "name" values in the array "tabNames" horizontally and then the others in to a drop down.
This is my html
<div id="categories" class="food-category-tab">
<script id="categoriesList" type="text/x-jsrender">
<ul id="myTab" class="nav nav-tabs">
{{if #index <=6}}
<li class="active"><a href="#home" data-toggle="tab">{{>name}} </a></li>
{{/if}}
{{if #index >6}}
<li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">More <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#dropdown1" data-toggle="tab">{{>name}}</a></li>
</ul>
</li>
{{/if}}
</ul>
</script>
</div>
And I call jsrender from the js file,where the function is written for loading the content into "tabNames" array, like below:
$("#categories").html($("#categoriesList").render(tabNames));
Can anybody tell what is wrong with the code and how to fix this?.
You are passing an array to render, so the whole template is being rendered for each item, including the wrapping <ul
.
Two ways to deal with that:
1: Call render with a boolean flag: noIteration
:
$("#categoriesList").render(tabNames, true);
then use a template that iterates over #data
such as:
<ul id="myTab" class="nav nav-tabs">
{{for #data}}
...
{{/for}}
{{if #data.length>6}}
...
{{/if}}
</ul>
Or else, 2: Pass in your array as a property:
var data = {names: tabNames};
$("#categoriesList").render(data);
And use a similar template, but iterating over names
, not #data
:
<ul id="myTab" class="nav nav-tabs">
{{for names}}
...
{{/for}}
{{if names.length>6}}
...
{{/if}}
</ul>
Either way, the template to show the two levels of list can be structured like this:
<ul id="myTab" class="nav nav-tabs">
{{for names.slice(0, 7)}}
<li class="active"><a href="#home" data-toggle="tab">{{>name}} </a></li>
{{/for}}
{{if names.length>6}}
<li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">More <b class="caret"></b></a>
<ul class="dropdown-menu">
{{for names.slice(7)}}
<li><a href="#dropdown1" data-toggle="tab">{{>name}}</a></li>
{{/for}}
</ul>
</li>
{{/if}}
</ul>
It is also possible to use {{if}}...{{else}}
etc. but it breaks the natural combined hierarchy of HTML and JsRender markup, and so is less elegant and less maintainable - like this:
<ul id="myTab" class="nav nav-tabs">
{{for names}}
{{if #index<=6}}
<li class="active"><a href="#home" data-toggle="tab">{{>name}} </a></li>
{{else #index===7}}
<li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">More <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#dropdown1" data-toggle="tab">{{>name}}</a></li>
{{else}}
<li><a href="#dropdown1" data-toggle="tab">{{>name}}</a></li>
{{/if}}
{{/for}}
{{if names.length>6}}
</ul>
</li>
{{/if}}
</ul>
Note about #data:
Any expression with #data can be simplified, since #data is the default current data context. You can write
<ul>
{{for #data}}
...
{{/for}}
{{if #data.length>6}}
...
{{/if}}
</ul>
as
<ul>
{{for}} {{!-- in this case #data is an array so this iterates over the array--}}
...
{{/for}}
{{if length>6}}
...
{{/if}}
</ul>
The whole template can be written like this:
<ul>
{{for slice(0, 7)}}
<li>{{>name}}</li>
{{/for}}
{{if length>6}}
<li><b>More:</b>
<ul>
{{for slice(7)}}
<li>{{>name}}</li>
{{/for}}
</ul>
</li>
{{/if}}
</ul>
There is a running sample here http://jsfiddle.net/BorisMoore/x0h9drr0/