Given a model:
MyModel = Backbone.Model.extend({
defaults: {
name: '',
age: -1,
height: '',
description: ''
}
});
and a View to render the model as a list:
MyView = Backbone.View.extend({
tagName: 'ul',
className: 'MyView',
render() {
var values = {
name: this.model.get('name'),
age: this.model.get('age'),
height: this.model.get('height'),
description: this.model.get('description')
}
var myTemplate = $('#MyView-Template').html();
var templateWithValues = _.template(myTemplate , values);
}
});
and a template loaded by the View:
<script type="text/template" id="MyView-Template">
<li class="name"><%= name %></li>
<li class="age"><%= age %></li>
<li class="name"><%= height%></li>
<li class="name"><%= description%></li>
</script>
everything works fine, although it is a contrived example, the real code has many, many more attributes in the model. The problem I'm experiencing is how to handle updates to the model.
I create an HTML form which has an appropriate input element for each field. The form is modelled and loaded as a template:
<script type="text/template" id="MyEditView-Template">
<input type"text" value="<%= name %>" /> <br />
<input type"text" value="<%= age%>" /> <br />
<input type"text" value="<%= height%>" /> <br />
<input type"text" value="<%= description%>" />
</script>
and loaded into a view:
MyEditView = Backbone.View.extend({
tagName: 'form',
className: 'MyEditView',
render() {
var values = {
name: this.model.get('name'),
age: this.model.get('age'),
height: this.model.get('height'),
description: this.model.get('description')
}
var myTemplate = $('#MyEditView-Template').html();
var templateWithValues = _.template(myTemplate , values);
}
});
When the user saves the form, the new values are set in the model (MyModel). However I do not want to re-render the entire original view, it takes too long and has many nested elements. I only want to update the HTML elements which have had their value changed in the model.
The problem is how can I elegantly link a model's attributes to HTML elements, so that I can do the following to an already rendered view:
- Iterate over a model's attributes.
- Determine which attributes have been modified.
- Only update the UI for modified attributes.
- Hide UI for any previously rendered attributes which should no longer be shown.
A the moment I have a rather ugly solution of a JavaScript lookup table (just an object) which maps an attribute name onto an HTML element string:
var AttributesMap = {
name: {
htmlRef: 'li.name',
attributeName: 'name'
},
age: {
htmlRef: 'li.age',
attributeName: 'age'
}
...
}
This feels hacky and has resulted in some pretty bloated code.