You can clone with
HTTPS or Subversion.
It seems that the switch from Backbone delegated events to jQuery events has introduced a bug whereby re-rendering a Backbone view and calling stickit again causes the bound elements to continue to set attributes on the model.
For example, I have a view that I render multiple times. Each time I render, I call stickit(). The first time it renders, there are no problems. But the second time, when I try to enter text into a field it keeps getting replaced with the previously set value from the model.
I see that stickit() calls unstickModel, but judging from the behavior it seems that the jQuery events are staying around. I see that you've wrapped view.remove to unbind these events but when I rerender I don't call view.remove.
I might be wrong and there is some other issue going on but we just upgraded stickit and it appears that this is what's causing the problem.
And I can confirm that adding this.$el.off('.stickit' + this.cid) to the beginning of my render function fixes the problem.
Should this line be added to unstickModel?
Ah, right, when stickit used view.events, events were always un-delegated before being re-delegated. Now that we are using $.off and $.on we should probably off events for a view before delegating. That way you wouldn't have to manually off events every time you (re-)render.
But you bring up a good point in that it would be beneficial to off events in unstickModel. With that change, we might want to rename unstickModel to unstickit.
With the added functionality, I think it makes sense to change unstickModel to unstickit. PRs are always welcome!
Ack, there is a little problem with this idea/implementation. Currently, the api allows for stickit() to be called multiple times in a view and old bindings are retained while new bindings are added. I don't use this feature much and I'm not sure if it is popular. It's probably not very common to re-render views often when using stickit, but that might be a more common, or better supported, use case.
We definitely should fix the re-render problem but should the api (multiple calls with retained bindings) be maintained?
By using stickit it find i re-render views less frequently as well however.
In 90% of the times where i "restick" its due to the fact that the collections that I source to selectOptions have changed and should refresh. Therefore it has always been convenient to not have to unstick before resticking.
I havent stumbled up on a use case where multiple binding hashes could be used, or adding/removing bindings dynamically. I just setup all my bindings in the bindings hash and since we are using event delegation, those where a dom element is present just works.
To only only try to have 1 model or 1 collection per view makes it easy to keep away from complicated views. I rather have sub views which communicates through mediator pattern.
@jr314159 - check out the unit tests.
I think that implementation and breaking the api will be ok. Give me some time to change and write-up some unit tests to verify your fix.
Oh, I think I see. So unstickit and unstickView would also need to accept an optional model argument. And instead of creating one jQuery event namespace for a view, we would need to create a new namespace for each view+model combination, like .stickit + view.cid + model.id. Is that the idea?
Yeah, I think we can simplify it by merging it all into one function - unstickit - since it probably isn't going to be a common use case to only unstick the view bindings or the model bindings. We can also keep it simple by calling unstickit(model) at the top of stickit.
I reworked PR #67 a little bit. I removed unstickModel and I took your suggestion on using the model.cid as a namespace. Now, a model is paired with a bindings configuration, so if you unbind a model with unstickit, then you unbind the corresponding view events as well.
@jr314159 - thanks for catching this issue. Can you try it out on your code base?
It's working great, thanks!
I have not been following the work that led up until unstickit - is all I need to do once I update change all my unstickModel to unstickit?
Yeah, it should work the same, but unstickit will also unbind the $el events as well. We had to make this change since we stopped delegating to backbone's events object.
Also, one difference now is that a model and a bindings hash are namespaced together, so calling unstickit with a particular model should unstick the model and the corresponding $el events.