Let's say I want to render a form using Underscore templates. Following the tutorial, I put in my Backbone view something like:
var CatFormView = Backbone.View.extend({
render: function () { this.$el.html(this.template(this.model.toJSON())); }
)};
and in my template, things like
<label for="cat-name">Cat name:</label>
<input id="cat-name" value="<%- catName %>" />
This is all well and good, but what if my form contains a select
element? Do I do something like:
<select id="cat-breed">
<option value="siamese" <% if (catBreed === "siamese") { %> selected <% } %>>Siamese</option>
<option value="persian" <% if (catBreed === "persian") { %> selected <% } %>>Persian</option>
<option value="scottish-fold" <% if (catBreed === "scottish-fold") { %> selected <% } %>>Scottish Fold</option>
...
</select>
or do I bind the input
elements directly in the template, and then set the value for the select
s in the view?
The first approach looks extremely cumbersome, the second spreads the data-binding logic over several files, making the web app that much less maintainable.
What would be a better solution here?
Edit: Loops! Now it seems so obvious, but I was still stuck on thinking of Underscore templates as markup. All thanks go to Clémentine.
<% var _catBreeds = [['siamese', 'Siamese'], ['persian', 'Persian'], ...]; %>
<select id="cat-breed">
<% for (var i = 0; i < _catBreeds.length; i++) { %>
<option value="<%= _catBreeds[i][0] %>" <% if (catBreed === _catBreeds[i][0]) { %>
selected <% } %> >
<%- _catBreeds[i][1] %>
</option>
<% } %>
</select>
Edit 2: Or, even better (and reusable):
<% function options(vals, selectedVal) {
// Can be moved into a helper library and injected when compiling template
vals.forEach(function (val, i) {%>
<option value="<%- val[0] %>" <%= (val[0] == selectedVal) ? "selected" : "" %>><%- val[1] %></option> <%
});
} %>
<select id="cat-breed">
<% options([["persian", "Persian"], ...], catBreed) %>
</select>
another option is to use another model for your form such as
[
{
'id': 'cat-breed',
'type': 'select',
'values': ["siamese", "scottish-fold", "persian"]
}
]
and then call
this.template(data_model: this.model.toJSON(), form_model:this.form_model.toJSON())
and then to build the form and with the form answers using loops.
this would allow you to have a more generic templating system, less cumbersome, but more difficult to code.