Scope inheritance for angular directives

我与影子孤独终老i 提交于 2019-12-11 02:18:33

问题


I've created a tab control using angular directives. It is consist of tab, tab-item directives with new scope and tab-item-header, tab-item-body directives for which scope is not declared.

If I understand correctly these directives use scope of tab-item directive because they are placed inside it. But when I try to get in markup property index which is declared inside tab-item scope it is undefined.

app.directive('tabItemHeader', function(){
return {
    require: '^tabItem',
    transclude: true,
    template: '<div ng-click="$parent.setCurrentTab(index)" ng-transclude></div>',
};});

app.directive('tabItemBody', function(){
return {
    require: '^tabItem',
    transclude: true,
    template: '<div ng-show="index==$parent.currentTabIndex"><div ng-transclude></div></div>'
};});

I've created a plunk http://plnkr.co/edit/HkXIOt8FKMw4Ja2GZtF1?p=preview to demonstrate it.

What is wrong?


回答1:


(EDIT) Giving some thought after the conversation in the comments, I came up with a better solution. Here is the modified plunk:

http://plnkr.co/edit/djNk8PPzXvngZOvAirMu?p=preview

The key points of this implementation are:

  • Every directive transcludes its content. This means that, even the innermost directives have access to the outer scope, as is expected. So no more $parent.$parent... awfulness.

  • Every directive has an isolated scope. As per the docs the isolated scope is side-by-side with the transcluded one; therefore all the private state of the directives (in this case the active tab, the index of each tabItem and some directive-specific functions) is kept in the isolated scope.

  • The directives communicate through the controllers. This pattern requires a top level "coordinator" (here the tab for all descendant directives and the tabItem for the tabItemHeader and tabItemBody).

By the way, if you want tabs, I would suggest Angular UI.


This was a crazy puzzler.

The reason for your problem is that the tabItem directive had no reason to transclude its contents; this transclusion created a sibling scope that totally messed up your logic!

Thus the answer is simple: remove these lines from the tabItem directive:

// REMOVE THEM!!!
transclude: true,
template: '<div ng-transclude></div>',

A plunkr with these lines commented out that prints scope ids: http://plnkr.co/edit/bBfEej145s1YjcE9n3Lj?p=preview (this helps with debugging; see what happens when you include these lines, the templates and the linker function see different scopes!)

And your plunkr forked, with those lines commented out: http://plnkr.co/edit/tgZqjZk0bRCyZiHKM0Sy?p=preview




回答2:


http://www.undefinednull.com/2014/02/11/mastering-the-scope-of-a-directive-in-angularjs/

This site explains scope inheritance very well.

Basically, if you add a scope section to the directive that you want to have you have a few options:

scope: false # this inherits the parent scope and allows upstream and downstream traffic (parent <=> child)
scope: true # this inherits the parent scope and allows downstream traffic (parent => child)
scope: {} # this does not inherit and creates the directive's very own scope (you can still inherit by specifying what you want to come down)

More details on specifying scope to inherit via the last option: What is the difference between & vs @ and = in angularJS



来源:https://stackoverflow.com/questions/19111696/scope-inheritance-for-angular-directives

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!