5
votes

I'm having trouble with {{actions}} on Ember (1.11.0) components not being triggered when the component has been added to the page dynamically. Oddly enough, it seems to be related to how the ember application has been added to the page - via the default template vs. added to a "rootElement".

Working JSBin: actions are triggered

Non-Working JSBin: actions aren't triggered

My Component Definition:

<script type="text/x-handlebars" data-template-name="components/foo-bar">
    <p>Component {{name}}</p>
    <button {{action "doIt"}}>Do It</button>  
</script>

App.FooBarComponent = Ember.Component.extend({
    click: function() {
        console.log('click fired! - ' + this.get('name'));
    },
    actions: {
        doIt: function() {
            console.log('doIt fired! - ' + this.get('name'));
        } 
    }
});

The click() event and doIt() action aren't triggered when the component has been added to the page dynamically. I'm using append() method to add the component to the page:

App.IndexController = Ember.Controller.extend({
    count : 1,
    actions: {
        createNewFoobBar: function() {
            this.set('count', this.get('count') + 1);
            var comp = this.container.lookup('component:foo-bar');
            comp.set('name', this.get('count'));
            comp.set('controller', this);
            comp.append();
        }
    }
});

In either case, actions are properly triggered when the component is part of the template:

{{foo-bar name="one"}}
1
I am able to get the click() event to fire on the component in my previous JSBin example by changing the append( ) call to appendTo('#content') However the component's action still doesn't work as expected. jsbinClavicle

1 Answers

2
votes

I found that it works if:

  • comp.appendTo('#content') is used instead comp.append(),
  • comp.set('controller', this); is removed, otherwise error is thrown.

Working jsbin: http://emberjs.jsbin.com/saquzupaye/edit?html,js,console,output

Why does comp.append() not working? We could see that components are appended to body instead of #content, and this behavior looks like unexpected, since rootElement: "#content" is defined.

From Guides:

"...The rootElement can be either a DOM element or a jQuery-compatible selector string. Note that views appended to the DOM outside the root element will not receive events. If you specify a custom root element, make sure you only append views inside it!" (from Event delegation guide)

"...At the end of the rendering process, the root view asks the RenderBuffer for its element. The RenderBuffer takes its completed string and uses jQuery to convert it into an element. The view assigns that element to its element property and places it into the correct place in the DOM (the location specified in appendTo or the application's root element if the application used append)." (from UnderstandingEmber: The view Layer guide).

So my opinion is that it's bug, and workaround is to append to root element manually by using appendTo().