Spine.js doesn't emit events when you change attributes on the model, it only fires an event when you call save()
on the model. It also doesn't perform any sort of dirty tracking, so you don't get update:keypath
style events out-of-the-box, it just fires a single update
event.
Here's a standard adapter for using Spine.js models with Rivets.js.
rivets.configure
adapter:
subscribe: (obj, keypath, callback) ->
obj.bind "update", callback
unsubscribe: (obj, keypath, callback) ->
obj.unbind "update", callback
read: (obj, keypath) ->
obj[keypath]
publish: (obj, keypath, value) ->
obj[keypath] = value
Using the above adapter, Rivets.js will update the in-memory attributes on your models when going from view-to-model (using a two-way binder such as value
or checked
) and will update the view (going from model-to-view) only when you call save()
on the model. This is just part of how Spine.js events work.
Unfortunately the above adapter will update every binding for that model, including bindings for properties that did not change. Alternatively, you can use something like Spine-Attribute-Events which does basic dirty tracking and fires an additional update:keypath
style event for the attributes that changed. This will be far more performant in terms of DOM operations as we're only updating what needs to be updated.
rivets.configure
adapter:
subscribe: (obj, keypath, callback) ->
obj.bind "update:" + keypath, callback
unsubscribe: (obj, keypath, callback) ->
obj.unbind "update:" + keypath, callback
read: (obj, keypath) ->
obj[keypath]
publish: (obj, keypath, value) ->
obj[keypath] = value
As you can see, this gives Rivets.js a more granular way to subscribe to individual attribute changes. The basic idea here is that Rivets.js will now update only the parts of the DOM for attributes that have changed.
Again all of this happens only when you call save()
, which is actually a nice feature because you can make as many intermediate changes to the model as you want, and then call save()
at the very end to have those changes reflected in the UI.