简体   繁体   English

EmberJS触发来自子组件的父组件的操作

[英]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) . 它包含2个组件 - 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. 但是,当我单击dropdown-item组件时,我无法在父组件上触发操作。

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. 我尝试设置targetObject和我在这里找到的许多其他组合。 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. 当我在每个帮助器中呈现子组件时,我确实在父组件中扩展了_yield 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. 通过使用yield ,您将为下拉项目提供与货币下拉列表相同的上下文,而不是货币下拉列表本身的上下文。 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. 它将这些组件耦合在一起,使得dropdown-item组件可能无法重复使用。
  2. The dropdown-item component is always going to call the action, not just when the parent component subscribes to it. dropdown-item组件总是调用该操作,而不仅仅是在父组件订阅它时。

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. 我个人根本不会使用yield ,而只是将下拉项的HTML硬编码到下拉组件类中。 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. 从长远来看,像这样的解决方法总会让我感到困惑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM