问题
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?.
回答1:
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/
来源:https://stackoverflow.com/questions/28584203/how-to-render-an-array-in-jsrender-without-iteration