1

unfortunately i am not able to figure out, how to receive an event of a component i use from within a component.

What i mean actually sounds harder than it is, consider the following toy example, with a component my-outer and another component my-inner (a short explanation follows the code, at the end i link to jsbin).

The templates:

<script type='text/x-handlebars' id='components/my-outer'>
  <div {{bind-attr class="isRed:red"}}>Buttons should toggle my background color</div>
  <button {{action "toggleRed"}}>It works from my-outer</button>
  {{my-inner action="toggleRed"}}
</script>

<script type='text/x-handlebars' id='components/my-inner'>
  <button {{action "action"}}>It doesn't work from my-inner</button>
</script>

The javascript:

App.MyOuterComponent = Ember.Component.extend({
  isRed: false,
  actions: {
    toggleRed: function() {
       this.toggleProperty("isRed");
    }
  }
});

my-outer contains a short text, with a background-color, which can be toggled from and to red by invoking the toggleRed action. the first button demonstrates that this works in principle.

now i would like to bind the default action of the second component to this same toggleRed action, that's the point of the following line.

{{my-inner action="toggleRed"}}

But on clicking the second button (which is part of my-inner) an error is thrown and the action is not fired.

How do I fix this example?

http://emberjs.jsbin.com/cabasuru/2/edit?html,js,console,output

Thanks so much in advance (and this is my first question on so, i am happy about any meta-critics)

Jonas Hörsch
  • 473
  • 3
  • 9
  • You need to experiment with `target`. –  Aug 03 '14 at 12:37
  • 1
    possible duplicate of [Ember: nested components events bubbling](http://stackoverflow.com/questions/24057289/ember-nested-components-events-bubbling) –  Aug 03 '14 at 12:38
  • @torazaburo, i don't think, it is a duplicate. the linked one is about events sent from yield, these are usually targeted to the outer controller (in which the element, was created). This one here is about explicit component event binding. (At least that's my take at it). – Jonas Hörsch Aug 03 '14 at 13:09

2 Answers2

2

Since Components work just like views, easiest way is to get the parentView and forward the action. You may have to handle the action in my-inner like following.

App.MyInnerComponent = Ember.Component.extend({
  isRed: false,
  actions: {
    toggleRed: function() {
      this.get('parentView').send('toggleRed');
    }
  }

});

You can see outer component can be accessed as parentView in inner component. Here is the working jsbin link http://emberjs.jsbin.com/cabasuru/5/edit

thecodejack
  • 12,689
  • 10
  • 44
  • 59
2

My question actually missed the main point. What goes wrong in the example above, is that the action helper in the inner component

<button {{action "action"}}>It doesn't work from my-inner</button>

does not trigger the default action associated with the component. Instead it invokes a new event named action, which is not allowed to bubble (due to the component confinement).

It turns out, there are two ways to solve that:

  1. Properly reroute the event in an actions block on the my-inner component

    <button {{action "my-action"}}>...</button>
    

    together with a definition of the my-action action for my-inner:

    App.MyInnerComponent = Ember.Component.extend({
      actions: {
        myaction: function(){
          this.sendAction();
        }
      }
    });
    

    This is basically, the idea @CodeJack proposes, with the difference, that here we rely on the wiring, which is set-up in the template of my-outer. http://emberjs.jsbin.com/cabasuru/3/edit

  2. As @torazaburo hinted at, setting the target property on the my-inner component to the my-outer component allows the event triggered from the action helper to bypass the component isolation.

    {{my-inner target=controller}} in the my-outer template and a <button {{action "toggleRed"}}>...</button> in the my-inner template.

Jonas Hörsch
  • 473
  • 3
  • 9