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

时间:2014-11-22 05:38:11

标签: javascript ember.js

我正在尝试创建一个下拉菜单组件。它包含2个组件 - currency-dropdown (parent)dropdown-item (child)。我能够渲染组件。但是当我点击dropdown-item组件时,我无法在父组件上触发操作。

我正在尝试将选定的组件数据发送到父组件。我尝试设置targetObject和我在这里找到的许多其他组合。我不知道问题是什么。当我在每个帮助器中呈现子组件时,我确实在父组件中扩展了_yield。一些帮助将非常感激。 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.

1 个答案:

答案 0 :(得分:5)

所以我找到了一种方法,但我认为这可能有点像黑客。您的问题是,就上下文而言,您的下拉项目无法访问您的货币下拉列表。通过使用yield,您可以为下拉项目提供与货币下拉列表相同的上下文,而不是货币下拉列表本身的上下文。这是一个奇怪的场景,因为你想要两全其美,但你只能拥有一个或另一个。因此,您可以执行此操作,而不是发送操作:

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

这会调用你想要的动作处理程序。只有两个警告:

  1. 它将这些组件耦合在一起,使dropdown-item组件可能无法重复使用。
  2. dropdown-item组件总是将调用该操作,而不仅仅是在父组件订阅它时。
  3. 此外,我不知道您的整个用例,但我认为您可能正在尝试使此组件可重用。我个人根本不会使用yield,而只是将下拉项的HTML硬编码到下拉组件类中。对某些特定于您的应用的内容进行硬编码会降低您在应用之外的可重用性,但会让您更轻松地在应用内部工作(这显然更为重要)。在使用变通方法之前,您可能需要再次了解如何使用这些组件。从长远来看,像这样的解决方法总会让我感到困惑。