【问题标题】:Angular event or command that signals the end of processing child directives表示处理子指令结束的角事件或命令
【发布时间】:2017-02-27 01:13:31
【问题描述】:

我目前正在编写一个标签导航示例来获得 Angular 的实践经验。此示例使用自定义指令和控制器继承。

Plunker 可以在here找到。

问题:一旦指令完成处理,我想选择一个默认选项卡来显示。但是在调用 myTabs 控制器的 selectTab 方法时(script.js $ctrl.selectTab(0) 中的第 41 行),Angular 还没有完成对 myTab 指令的处理(其中生成标签链接),所以tabs数组为空,选择失败。

我尝试立即使用 $timeout,但失败了。 $timeout 仅适用于设置 500 毫秒的延迟,这很 hacky。

是否有可用的事件或命令表明 Angular 结束处理某些指令,尤其是相互继承的指令?

我怀疑正在发生的事情:

myTabs 指令完成处理然后触发它的链接函数,但它在myTab 指令完成处理之前被触发。我不能将selectTab 方法调用放在myTab 链接函数中,因为会被多次调用(基于处理的标签数量。)希望我能清楚地解释这一点......我需要按摩

app.directive('myTabs', ['$timeout', function($timeout) {

    return {
        restrict: 'E',
        transclude: true,
        controllerAs: 'myTabsCtrl',
        templateUrl: 'my-tabs.htm',
        scope: {},
        controller: function ($scope) {

            vm = this;

            this.tabs = [];

            this.addTab = function (tab) {
                this.tabs.push(tab);
            };

            this.selectTab = function selectTab (tabIndex) {

                for (var i = 0; i < this.tabs.length; i++) {

                    this.tabs[i].selected = (i === tabIndex ? true : false);

                }

            };

        },
        link: function ($scope, $element, $attrs, $ctrl) {

            $timeout(function () {
                $ctrl.selectTab(0);
            });

        }
    };

}]);

app.directive('myTab', function() {

    return {
        restrict: 'E',
        require: '^^myTabs',
        transclude: true,
        templateUrl: 'my-tab.htm',
        scope: {
            title: '@'
        },
        link: function (scope, element, attrs, ctrl){

            scope.tab = {
                title: scope.title,
                selected: false
            };

            ctrl.addTab(scope.tab);

        }
    };

});

【问题讨论】:

  • 这似乎是根本原因:“对于每个指令,其控制器和预链接函数在其子指令的控制器和预链接函数之前执行”
  • 它这样做是因为指令使用templateURL 异步获取模板。如果指令使用template,那就另当别论了..

标签: angularjs angular-directive


【解决方案1】:

每个单独的选项卡都向父指令控制器注册自己。注册时只需在第一个选项卡上设置selected 标志:

this.tabs = [];
this.addTab = function (tab) {
    console.log("add tab ", tab);
    if (!this.tabs.length) {
        //Set flag for first tab to register
        tab.selected = true;
    };
    this.tabs.push(tab);
};

DEMO on PLNKR

【讨论】:

  • 谢谢 George,但我有兴趣了解如何跟踪嵌套指令模板的最终 DOM 渲染,以便可以进行单个调用来执行任何操作,例如在此设置默认选项卡案子。想知道这是否可以实现的原因是因为我预测在未来构建完整的应用程序时这将是一个问题。
【解决方案2】:

AngularJS 1.5.3 引入了$postLink 生命周期钩子:

生命周期钩子

指令控制器可以提供以下方法,Angular 在指令的生命周期中调用这些方法:

  • $postLink() - 在此控制器的元素及其子元素被链接后调用。与 post-link 函数类似,此钩子可用于设置 DOM 事件处理程序并进行直接 DOM 操作。请注意,包含 templateUrl 指令的子元素将不会被编译和链接,因为它们正在等待其模板异步加载,并且它们自己的编译和链接已暂停,直到发生这种情况。

--AngularJS $compile Service API Reference -- Life-cycle hooks

$postLink 生命周期挂钩在这种情况下不起作用,因为指令使用 templateUrl。它也不适用于在 postlink 之后构建 DOM 的指令; ng-repeatng-ifng-include

【讨论】:

  • 作为一个附带问题,我是否正确理解术语“链接”意味着将元素附加到 DOM?例如“在此控制器的元素及其子元素被链接后调用。”
  • 是的,除了ng-repeatng-ifng-switch 和其他进行手动嵌入的指令。
猜你喜欢
  • 1970-01-01
  • 2021-02-28
  • 2011-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-28
  • 1970-01-01
  • 2011-04-29
相关资源
最近更新 更多