gmac / backbone.epoxy

Declarative data binding and computed models for Backbone
http://epoxyjs.org
MIT License
615 stars 89 forks source link

Get notified when a collection binding has been rendered #59

Open Prinzhorn opened 10 years ago

Prinzhorn commented 10 years ago

Following up this tweet https://twitter.com/Prinzhorn/status/416960488941948928

@gmacwilliam is there some sort of render event for 'collection: $collection' binding? For attaching https://github.com/bradbirdsall/Swipe or similar

@Prinzhorn no, but you could handle the source collection's add, remove, sort, and reset events on your own to map model data to the view

@gmacwilliam I initialize the view with a collection that is already filled, so there won't be any of these four events for the first render

As I said in the tweet, I want to initialize Swipe (a mobile first image carousel/slider). I use the collection binding to render a list of N images to a container. The collection I pass into the view is already populated with data. There won't be any events (I verified by listening for all on it).

How do I know when to initialize the image slider? Destroying/reinitializing can be done by listenting to sort, add etc. but what about the very first run? The images are not in the DOM right after Backbone.Epoxy.View.prototype.initialize.apply(this, arguments);, so there must be something async going on.

Prinzhorn commented 10 years ago

Here's another use case which is currently not possible: lazy loading of images. The images which are visible right after rendering need to be replaced asap. But I don't know when they're rendered.

Edit: I've come up with an elegant solution, but I don't know how to generalize it for all handlers. I've changed the bottom of the set method of the collection from

$element.append(frag);

to

$element.append(frag).trigger('handled:collection').trigger('handled');

Now in any parent view I can do this:

Backbone.View.extend({
    events: {
        'handled:collection .listview': 'lazyLoad'
    }
});

which is awesome. The event bubbles and everything is firing rainbows.

If you agree than it would be great to have this automatically for every bindingHandler (maybe pass some useful data along the event as well) then I guess it should be really easy to have this at a central place (I don't know the code well enough though).

adamsea commented 9 years ago

+1 for this.

I think the more generalized concern here is the ability to attach a listener for individual bindingHandlers, or a more generic listener perhaps after applyBindings is called. Similar to an 'afterRender' style event for Epoxy.

gmac commented 9 years ago

Write a formal spec please, gents. I guess I sort of understand what you're trying to do (get events off of Epoxy view components after they perform rendering tasks?), but these sound like more philosophical ideals than technical specifications. What event(s) do you want fired, when are they triggered, and who triggers them?

kevincolten commented 9 years ago

+1 for this

gmac commented 9 years ago

@mistakevin : What do you want to see reported? How would you collect it, and what does the reported data look like? Without having had the need myself, I need a formal spec as to what others would like to see the library do.

kevincolten commented 9 years ago

Actually, this problem was solved for me by utilizing Backbone LayoutManager. The "afterRender" event will trigger after the items have rendered. That being said, the spec would be just that, the parent view setting off some sort of event that says that all children have been rendered.