2
votes

So I have this issue where Ember will not render my view more than once, even after I have destroyed it.

The code I have, works without using components, so it is probably some issue with the actual view not being destroyed properly.

I render into an outlet in my ApplicationRoute

App.ApplicationRoute = Em.Route.extend({
  actions: {
    showModal: function() {

      // This does not work the second time:
      this.render('modal', {
        into: 'application',
        outlet: 'modal'
      });

    }
  }
});

I set up an event listener for when the Bootstrap modal is hidden

App.BaseModalComponent = Em.Component.extend({
  afterRenderEvent: function() {
    var self = this;
    this.$('.modal')
        .on('hidden.bs.modal', function(){

          // I am destroying the component, 
          // when the modal is hidden
          self.destroy();

        })
        .modal();
  }
});

The afterRenderEvent is a listener I have attached to the view's afterRender event.

See here for markup, etc.: http://emberjs.jsbin.com/wolicutiwiro/1/edit

A working example without using components: http://emberjs.jsbin.com/lodamojikaqo/1/edit

1
why are you calling destroy?..why not disconnectOutlet from router? Any specific reason? - thecodejack
@CodeJack That's what worked in my view. I didn't know about the disconnectOutlet method before. I am closer to a solution after looking at Ghost source code. But I can't figure out how to call disconnectOutlet from my hidden.bs.modal event listener. - Ronni Egeriis Persson
ok i will edit your jsbin about disconnectOutlet - thecodejack
Unfortunately that example uses as different method of displaying the modal view, as the modal is visible as soon as it's rendered. It's different with a Bootstrap modal. - Ronni Egeriis Persson

1 Answers

0
votes

Check this JSBin It does what you want.

App.ApplicationRoute = Em.Route.extend({
    actions: {
        showModal: function() {

          // This does not work the second time:
          this.render('modal', {
            into: 'application',
            outlet: 'modal'
          });

        },
        closeModal: function() {
            console.log("closing modal");
            return this.disconnectOutlet({
              outlet: 'modal',
              parentView: 'application'
            });
        }   
     }  
});

I believe the main challenge is that I cannot call a closeModal action from a button in my modal view. Bootstrap itself handles hiding the modal, but I need to disconnect the outlet to allow the same or another modal to render.

In order to call this action from your component, you have to send the action from the component to the controller current templates controller:

App.BaseModalComponent = Em.Component.extend({
  afterRenderEvent: function() {
    var self = this;
    this.$('.modal')
        .on('hidden.bs.modal', function(){

          self.sendAction('action');

        })
        .modal();
  },
});

And when you use your component, make sure to assign the action name:

  <script type="text/x-handlebars" data-template-name="modal">
    {{#base-modal action='closeModal'}}
      <p>One fine body&hellip;</p>
    {{/base-modal}}
  </script> 

The action will bubble from the controller to the route. This solution allows you to use bootstrap exactly as is, but I find that the solution Code Jack suggested to be much more Ember.