I'm using Rivets.js for two two-way data binding in a Backbone project and would like to implement iteration binding. The documentation suggests iteration binding is possible, but there are no examples available. I am using a simple Rails API to send JSON to the client and want to iterate over the contents. Has anyone had any success getting this functionality working in Rivets.js?
Reference material: Simple Example using Backbone.js and Rivets.js
jsFiddle here: http://jsfiddle.net/rhodee/3qcYQ/1/
From the Rivets.js site
Iteration Binding
Even though a binding routine for each-item will likely be included in Rivets.js, you
can use the data-html binding along with a set of formatters in the interim to do
sorting and iterative rendering of collections (amongst other cool things).
<ul data-html="model.tags | sort | tagList"></ul>
As of 0.3.2 there is now a data-each-[item] binding for exactly this purpose.
<ul>
<li data-each-todo="list.todos">
<input type="checkbox" data-checked="todo.done">
<span data-text="todo.summary"></span>
</li>
<ul>
For previous versions of Rivets.js, the work-around that you've referred to is to implement the iterative rendering with a formatter — for example you would have a data-html
binding with model.items | itemList
where the itemList formatter just loops over the array and returns some rendered HTML.
rivets.formatters.itemList = (array) ->
("<li>#{item.name}</li>" for item in array).join ''
Expanding on this answer:
As of 0.3.2 there is now a data-each-[item] binding for exactly this purpose.
Note that you will need to specifically modify your Rivets adapter to work with a Backbone Collection, as the out-of-the-box examples on the Rivets.js site do not fly with this use case.
You'll need something like this in your rivets.configure({ adapter: ... })
:
...
read: function( obj, keypath ) {
return obj instanceof Backbone.Collection
? obj["models"]
: obj.get(keypath)
}
And the JS Fiddle: http://jsfiddle.net/tigertim719/fwhuf/70/
For bonus points, Collections embedded in Models will require additional handling in your adapter.
For more information, check this post on Rivets.js Github issues:
Binding to Backbone.Collection with the data-each- binding
UnderscoreJS is integrated in Backbone so you can use its native methods like _.each() or use the integrated Backbone Collection underscore methods.
Is it this what you are looking for?
cayuu's answer was correct.
But the rivets.js reference in the fiddle was not working, so the result is not displaying.
Check out the version below to see the action.
http://jsfiddle.net/tigertim719/fwhuf/70/
rivets.configure({
adapter: {
subscribe: function(obj, keypath, callback) {
obj.on('change:' + keypath, callback);
},
unsubscribe: function(obj, keypath, callback) {
obj.off('change:' + keypath, callback);
},
read: function(obj, keypath) {
return obj instanceof Backbone.Collection ? obj["models"] : obj.get(keypath);
},
publish: function(obj, keypath, value) {
obj.set(keypath, value);
}
}
});
The most important part is
read: function(obj, keypath) {
return obj instanceof Backbone.Collection ? obj["models"] : obj.get(keypath);
},
That tells rivets how to read your collection and model from Backbone.