didInsertElement on new elements


#1

I have a topic list that receive a bootstrap popover event on page load.

But when I add new topics to this list without reload page I can’t bind popover event in this new topic.

My code is organized in this way:

Forum route:

export default Ember.Route.extend({
  model: function() {
    return Ember.RSVP.hash({
      run: this.store.find('run', this.modelFor('dialogo.admin.manager').get('id')),
      topics: this.store.find('topic', { run: this.modelFor('dialogo.admin.manager').get('id') })
    });
  },
  setupController: function (controller, model) {
    controller.set('runID', this.modelFor('dialogo.admin.manager').get('id'));
    controller.set('model', model.topics);
    controller.set('currentRun', model.run);
  }
});

Forum Controller:

export default Ember.Controller.extend({
  needs: ['application'],
  activeUser: Ember.computed.alias("controllers.application.model"),
  actions: {
    createTopic: function() {
      var
        store = this.get('store'),
        user = this.get('activeUser'),
        run = this.get('currentRun'),
        topic;

      topic = store.createRecord('topic', {
        content: '',
        run: run,
        moderator: user
      });

      this.set('newTopic', topic);
    },
    saveNewTopic: function() {
      var newTopic = this.get('newTopic');
      var topicList = this.get('model');

      newTopic.save().then(function(topic){
        topicList.pushObject(topic);
        Ember.$('#newTopic').modal('hide');
      });
    },
    deleteTopic: function (topic) {
      topic.destroyRecord();
    }
  }
});

Forum View:

export default Ember.View.extend({
  didInsertElement: function() {
    this.$('[data-toggle="popover"]').popover({
      html : true,
      content: function() {
        var delID = Ember.$(this).attr('data-del');
        return Ember.$('#alertDel' + delID).html();
      }
    });
  }
});

Forum Template:

  <tbody>
    {{#each topic in model}}
      <tr>
        <th scope="row">{{topic.id}}</th>
        <td>{{topic.content}}</td>
        <td>{{topic.posts.length}}</td>
        <td>0</td>
        <td>
          <button class="btn btn-default" type="button" data-toggle="popover" data-placement="top" data-trigger="focus" data-del="{{topic.id}}" title="ATENÇÃO: Deletar tópico">
            DEL
          </button> |
          <span>EDIT</span> |
          <span>PEND</span> |
          <span>MOD</span>
          <div id="alertDel{{topic.id}}" style="display: none;">
            Você deseja deletar o tópico #ID {{topic.id}}?
            Essa ação não poderá ser desfeita.
            <br><br>
            <button class="btn btn-danger" {{action 'deleteTopic' topic}}>Sim</button> |
            <button class="btn btn-default">Não</button>
          </div>
        </td>
      </tr>
    {{else}}
      <tr>
        <td rowspan="5">Nenhum tópico encontrado...</td>
      </tr>
    {{/each}}
  </tbody>

So, when I execute saveNewTopic and add this new topic to topicList, I lost my popover event.

I searched for an answer but found nothing…

Anyone have a clue about how can I bind my popover event on new topic instances?

Thanks in advance!


#2

Its because your only calling popover on the initial load, any new items won’t have the popover unless you observe for changes to the topics array and invoke .popover on the new topics.

I’d suggest moving the tr into a component. so you end up with

{{#each topic in model}}
   {{topic-row model=topic}}
{{/each}}

Then in you topic-row component you would attach the popover event on didInsertElement using the afterRender queue.

Ember.run.scheduleOnce('afterRender', this, function(){
  this.$('[data-toggle="popover"]').popover({
    html : true,
    content: function() {
      var delID = Ember.$(this).attr('data-del');
      return Ember.$('#alertDel' + delID).html();
    }
  });
})

probably also worth calling .popover('destroy') when the component is destroyed via willDestroyElement.

or see this http://jsbin.com/zopod/1/edit?html,css,js,output you can use selector: '.target'


#3

@Snake thks a lot, use components works like a charm! :slight_smile:


#4

This is a common problem when using jQuery to enhance UI controls created at runtime. Great solution indeed