简体   繁体   中英

EmberJS trigger action on parent component from child

I am trying to create a drop down menu component. It comprises to 2 components - currency-dropdown (parent) , dropdown-item (child) . I am able to render the components. But when I click on the dropdown-item component I am unable to trigger an action on the parent component.

I am trying to send the selected components data to the parent component. I tried setting the targetObject and many other combinations I found here. Im not sure what the problem is. I did extend _yield in the parent component as I was rendering the child components in an each helper. Some help would be much appreciated. Here is what I've got so far.

App.CurrencyDropdownComponent = Ember.Component.extend({
    actions: {
        itemSelected: function(item) {
            console.log(item);
        }
    },
    _yield: function(content, options) {
        var get = Ember.get,
        view = options.data.view,
        parentView = this._parentView,
        template = get(this, 'template');
        if (template) {
            view.appendChild(Ember.View, {
                isVirtual: true,
                tagName: '',
                _contextView: parentView,
                template: template,
                context: get(view, 'content'),
                controller: get(parentView, 'controller'),
                templateData: { keywords: parentView.cloneKeywords() }
            });
        }
    }
});

App.DropdownItemComponent = Ember.Component.extend({
    click: function() {
        this.sendAction('selectItem', this.origContext);
    }
});

<script type="text/x-handlebars" id="index">
  <header>
    {{#currency-dropdown currencies=model}}
      {{#dropdown-item targetObject=view selectItem="itemSelected"}}
        <span class="cdd-selected-tick">&#10004;</span>
        <span class="font-13">{{name}}</span>
        <span class="push-right font-11">{{symbol}}</span>
      {{/dropdown-item}}
    {{/currency-dropdown}}
  </header>
</script>

<script type="text/x-handlebars" id="components/currency-dropdown">
  <div class="cdd-box">
    <input class="cdd-input" type="hidden"/>
    <div class="cdd-selected-box" {{action "toggleDropDown"}}>
      <strong>Currency</strong>
      <span class="uppercase"> {{currencies.0.currencyCode}} </span> 
      {{currencies.0.symbol}}
      <div class="down-arrow"></div>
    </div>
    <ul class="cdd-selection-box" >
      {{#each item in currencies}}
         <li>{{yield}}</li>
      {{/each}}
    </ul>
  </div>
</script>

For anyone interested I have made my solution an addon.

So I found a way to do it, but I think it might be a bit of a hack. Your problem is that, in terms of contexts, your dropdown-item shouldn't have access to your currency-dropdown. By using yield , you're giving the dropdown-item the same context that the currency-dropdown has, not the context of the currency dropdown itself. It's a weird scenario, as you kind of want the best of both worlds but you can only have one or the other. So, instead of sending an action, you can do this:

this.get('parentView').send('itemSelected', this.origContext);

That will call the action handler you want. There's just two caveats:

  1. It couples these components together such that the dropdown-item component might not be reusable.
  2. The dropdown-item component is always going to call the action, not just when the parent component subscribes to it.

Also, I don't know your entire use case, but I think you might be trying to make this component too reusable. I would personally not use yield at all, and instead, just hardcode the HTML for the dropdown items into the dropdown component class. Hardcoding some things that are specific to your app makes it less reusable outside of your app, but makes it much easier to work with inside of your app (which is clearly more important). You might want to take a second look at how you're using these components before you use a workaround. Workarounds like these always come back to bite me in the long run.

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