EmberJS action launches parent component from child

I am trying to create a dropdown menu component. It consists of two components - currency-dropdown (parent)

, dropdown-item (child)

. I can display components. But when I click on the component dropdown-item

, I cannot call the action on the parent component.

I am trying to send data of selected components to a parent component. I tried setting targetObject and many other combinations I found here. I'm not sure what the problem is. I kept expanding _yield

in the parent component as I was providing child components in every helper. Some help would be much appreciated. Here's what I have 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 everyone concerned, I made my solution an addon.

+3


source to share


1 answer


So, I found a way to do this, but I think it might be a bit of a hack. Your problem is that in terms of contexts, your dropdown should not be able to access the dropdown. By using yield

, you are providing the dropdown with the same context as the currency dropdown, not the currency dropdown context. This is a weird scenario as you want the best of both worlds, but you can only have one or the other. So, instead of dispatching an action, you can do this:

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

      

This will invoke the action handler you want. There are only two caveats:



  • It combines these components together so that the component dropdown-item

    cannot be reused.
  • A component dropdown-item

    will always invoke an action, not just when its parent component is subscribed.

Also, I don't know your entire use case, but I think you might be trying to make this component too reusable. I personally wouldn't use it yield

at all, but instead just copied the HTML for the dropdowns into the dropdown coclass. Hardcoding some things that are specific to your application make it less reusable outside of your application, but make it easier to work with inside your application (which is clearly more important). You might want to take a look at how you use these components before using the workaround. Workarounds like these always come back to bite me in the end.

+5


source







All Articles