简体   繁体   中英

ember.js and bootstrap accordion - the “ember way” of creating the view

My question is not how to make a bootstrap accordion work, but to try to make sure that I understand the "ember" way of doing things.

I've created a working example of a bootstrap accordion here (as of 3/12/2013): http://jsfiddle.net/nrionfx/s59fA/

DEBUG: ——————————- 
DEBUG: Ember.VERSION : 1.0.0-rc.1
DEBUG: Handlebars.VERSION : 1.0.0-rc.3
DEBUG: jQuery.VERSION : 1.9.1 
DEBUG: ——————————-

To make the accordion collapse properly, I had to create an observer to watch the controller.content array. If I did not do this, the accordion did not collapse when the elements were inserted, even if I placed the $().collapse into the didInsertElement hook.

App.IndexView = Em.View.extend
    templateName: 'index'
    contentObserver: ( ->
        Ember.run.next this, ->
            @.$('.collapse').collapse()
      ).observes('controller.content')

Now, this works, but my question is: Is this the appropriate way of doing this under the ember framework, or should this be somewhere else, such as the didInsertElement call?

---- Update ---- Final jsFiddle: http://jsfiddle.net/nrionfx/s59fA/16/

I would recommend wrapping your items in an own View. In this case, you can use the didInsertElement hook to run your logic.

So your handlebars would look like:

{{#each item in controller}}
   {{view App.ItemView contextBinding="item"}}        
{{/each}}

Just move the current contents of your loop to this new template. The View would look somehow like this:

App.ItemView = Em.View.extend
    templateName: 'item'
    didInsertElement: ( ->
        Ember.run.next this, ->
            @.$().collapse()
      )

I think this would be the most emberish approach. This seems better, since the logic is not rerun on every swap of the controller's content. As you already said the didInsertElement hook is the most appropriate place to integrate with 3rd party libraries.

Hint: It did not work, when you placed the logic in the didInsertElement hook of your IndexView, because at that time the contained collection is not rendered yet.

Is this the appropriate way of doing this under the ember framework, or should this be somewhere else, such as the didInsertElement call?

For sure the right place to do this is via didInsertElement. As @mavilein mentioned you can do this by creating a view for each child element.

Another approach you might consider is using the afterRender queue. For example:

App.IndexView = Em.View.extend
    templateName: 'index'
    contentObserver: ( ->
        Ember.run.next this, ->
            @.$('.collapse').collapse()
      ).observes('controller.content')

Check out @machty's excellent post on the ember run loop or Run jquery at the end of Ember.CollectionView rendering

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM