AngularJS:指令转换范围丢失

时间:2014-04-21 16:07:56

标签: javascript angularjs angularjs-directive angularjs-scope

我正在构建一个指令,我正在调用'requires-authorization'来包装ng-if指令。我想用它如下:

<requires-authorization role='SuperUser'>
<!— super secret user stuff goes here, within
   the scope of this view's controller —>
</requires-authorization>

我已经达到了:

angular.module('myApp').directive('requiresAuthorization', function() {
   return {
    template: '<div ng-if=\'iAmInRole\' ng-transclude></div>',
    restrict: 'E',
    transclude: true,
    scope: {
        role: '@'
    },
    controller: function($scope, UserService) {
       $scope.iAmInRole = (UsersService.myRoles.indexOf($scope.role) !== -1);
    }
  };
});

这样可行,但指令中包含的内容会丢失其范围,特别是它所在视图的控制器范围。我在俯瞰什么?

jsfiddle供参考:http://jsfiddle.net/HbAmG/8/ 请注意auth值如何不在指令中显示,但在指令外可用。

3 个答案:

答案 0 :(得分:4)

ng-ifng-transclude指令都在您的指令中执行转换。在这种情况下,内置转换机制不能正常工作,您应该实现自己的ngIf以使其按预期工作:

<强>的JavaScript

app.directive('requiresAuthorization', function () {
    return {
        template: '<div ng-transclude></div>',
        restrict: 'E',
        transclude: true,
        scope: {
            role: '@'
        },
        controller: function ($scope) {
            $scope.iAmInRole = true;
        },
        link: function(scope, element, attr, ctrl, transcludeFn) {
            transcludeFn(function(clone) { // <= override default transclude
                element.empty();
                if(scope.iAmInRole) { // <= implement ngIf by yourself
                  element.append(clone);
                }
            });
        }
    };
});

Plunker:http://plnkr.co/edit/lNIPoJg786O0gVOoro4z?p=preview

如果ng-show是您使用的选项,而不是ng-if,那么它也可能是一个非常简单的解决方法。唯一的副作用是隐藏数据将在DOM中显示并使用CSS .ng-hide {display: none !important;}隐藏。

JSFiddle:http://jsfiddle.net/WfgXH/3/

此帖子也可能对您有用,因为它描述了类似的问题:https://stackoverflow.com/a/22886515/1580941

答案 1 :(得分:2)

您使用ng-if。它也会进行转换,不幸的是使用它自己的范围的子范围,而范围又是隔离范围。

以下是Batarang的截图。第一个是使用ng-if的代码。 4是隔离范围,6是转换内容。

Scopes with ng-if

同样没有ng-if。被剔除的内容现在是5,是隔离范围的兄弟,更重要的是控制器范围的子代。

Scopes without ng-if

答案 2 :(得分:2)

在指令中定义scope属性后,它将成为一个独立的范围。无法访问外部(在某种程度上,唯一的方法是丑陋且应该避免),除了通过scope属性传递给它的东西。

您需要将它们传递给指令:更新您的jsfiddle

<requires-authorization role='Admin' data-auth-value='authValue' data-unauth-value='unAuthValue'>
  <div>Inside directive. For Admin eyes only</div>
  <p>{{authValue}}</p>
</requires-authorization>

// your directive scope
scope: {
  role: '@',
  authValue: '=',
  unauthValue: '='
}

或者创建一个服务/工厂作为中间人进行沟通。