AngularJS组件绑定函数而不是发出事件

时间:2016-05-17 13:47:58

标签: angularjs

我正在构建一个简单的视图:

<tabulation tabulation-data="vm.tabs"></tabulation>

<div ng-switch="vm.activeTab.id">
    <account-details ng-switch-when="details"></account-details>
    <account-history ng-switch-when="history"></account-history>
    <account-summary ng-switch-when="summary"></account-summary>
    <account-dashboard ng-switch-when="dashboard"></account-dashboard>
</div>

基本上,正如我现在所做的那样,制表将$emit一个事件发送给父account控制器,它将更新vm.activeTab属性以切换不同的标签内容。< / p>

我的一位同事告诉我,在tabulation组件上使用绑定(&amp;)可能会更优雅,该组件将使用父account组件传递的函数...

不幸的是,我不了解它是如何运作的:

account控制器:

function PocDemoContainerController($scope) {
    var vm = this;

    vm.tabs = [{
        label: 'Details',
        id: 'details'
    },
    {
        label: 'History',
        id: 'history'
    },
    {
        label: 'Summary',
        id: 'summary'
    },
    {
        label: 'Dashboard',
        id: 'dashboard'
    }];

    vm.activeTab = vm.tabs[0];

    // this is the function that I want to pass to the tabulate component
    vm.onClickTab = function (tab) {
        vm.activeTab = tab;
    };

    ...
}

制表组件html:

<tabulation tabulation-data="vm.tabs" on-click-tab="vm.onClickTab(tab)">
<div class="tabulation">

    <nav class="container">
        <button class="tabulation__mobile-toggle"
                ng-class="{'tabulation__mobile-toggle--is-open': vm.mobileTabulationIsOpen}"
                ng-click="vm.toggleMobileTabulation()">{{vm.activeTab.label}}</button>

        <ul class="tabulation__container"
            ng-class="{'tabulation__container--is-open': vm.mobileTabulationIsOpen}">

            <li class="tabulation__item"
                ng-repeat="tab in vm.tabs"
                ng-class="{'tabulation--is-active': vm.isTabActive(tab)}">

                <a id={{tab.id}}
                   class="tabulation__link"
                   ng-click="vm.onClick(tab)">{{tab.label}}</a>
            </li>
        </ul>
    </nav>    
</div>
</tabulation>

制表控制器:

...

module.exports = {
    template: require('./tabulation.html'),
    controller: TabulationController,
    controllerAs: 'vm',
    bindings: {
        tabulationData: '<',
        onClickTab: '&' // this should send data up, right?
    }
};

制表控制器:

function TabulationController($scope) {
    var vm = this;

    ...

    vm.onClick = function (tab) {
        vm.onClickTab(tab); // This is the function from the parent I want to call
    };

    ...
}

TabulationController.$inject = [
    '$scope'
];

module.exports = TabulationController;

因此,tabulation控制器可以看到并调用vm.onClickTab,但传递的参数值不会传递给父account组件控制器......

我如何实现这一目标? (甚至可能那样吗?)

2 个答案:

答案 0 :(得分:12)

好的!我终于找到了如何做到这一点,而且根本不直观(有角度的文档不会告诉你这个)。

根据上面的示例,我的制表需要告诉父组件哪个选项卡现在处于活动状态,以便它可以更新视图。

以下是:

  • 在您的父组件上声明一个函数:
    • vm.onClickTab = function (tab) { ... };
  • 将该功能放在您的子组件上。
    • <tabulation on-click-tab="vm.onClickTab(tab)"
    • 重要:如果您要传递参数,请使用与您在子组件中定义的名称相同的名称。
  • 在您的子组件中,声明一个新函数,该函数应调用父回调。
    • vm.onClick = function (tab) { ... };
  • 现在,这里出现了未在任何地方提到的部分:你必须使用一个对象来调用父的回调函数,其中一个属性使用与将该回调传递给子组件时定义的相同名称: / LI>

function TabulationController($scope) {
    ...
    vm.onClick = function (tab) {
        // The onClickTab() function requires an object with a property
        // of "tab" as it was defined above.
        vm.onClickTab({tab: tab});
    };
    ...
}
  • 现在,当调用vm.onClick()时,它会调用带有对象的父回调,并将参数传递给它,而父对象现在可以使用该数据来更新视图。

答案 1 :(得分:0)

查看你的Tabulate组件html我想知道你发送的tab参数是什么。它是您控制器的本地财产吗?它似乎不是因为它没有vm前缀(或您定义的任何其他名称)。你的代码似乎是合法的,它是参数起源不明确,因此未定义。 给我们一个暗示它的起源进行进一步分析。