自定义子指令访问父指令的作用域

15 浏览
0 Comments

自定义子指令访问父指令的作用域

我在我的AngularJS应用中有两个自定义指令。一个充当父指令,另一个充当子指令。我想在子指令中访问父指令的作用域。但是我没有得到期望的输出。\n

{{myName}}

    

\n我的脚本如下:\n

var app = angular.module("sampleApp",[]);
app.controller("CountryCtrl",function($scope){
    $scope.myName = "India";
});
app.controller("StateCtrl",function($scope){
});
app.directive("state",function(){
    return {
        restrict : 'E',
        transclude: true,
        scope : { myName  : '=nameofthestate'},
        template:"**   {{myName}} is inside {{$parent.myName}}"
    }
});
app.directive("city",function(){
    return {
        restrict : 'E',
        require:'^state',
        scope : { myName  : '=nameofthecity'},
        template:"****   {{myName}} is inside {{$parent.myName}} which is in {{$parent.$parent.myName }} "
    }
});

\n对应的JSFiddle在https://jsbin.com/nozuri/edit?html,js,output中可用。\n我得到的输出是:\n

India
** Tamilnadu is inside India
**** Chennai is inside India which is in Tamilnadu

\n期望的输出是:\n

India
** Tamilnadu is inside India
**** Chennai is inside Tamilnadu which is in India

\n有人能告诉我在这里我做错了什么吗?

0
0 Comments

当AngularJS遇到transclude指令时,它会在用template或templateUrl内容替换之前克隆HTML。然后,当遇到ng-transclude指令时,它会编译被传递的内容,但是将它链接到父作用域而不是指令的隔离作用域。因此,被传递的内容仍然可以访问父控制器及其内容,而指令的HTML具有隔离作用域(或者可能是一个新的作用域)。

这个问题的出现是因为当使用transclude指令时,被传递内容的作用域会被链接到父作用域,而不是指令的隔离作用域。这可能会导致在指令内部无法访问父作用域的数据或方法,限制了指令的灵活性和可复用性。

解决这个问题的方法是使用$compile服务手动链接被传递内容的作用域到指令的隔离作用域。通过在指令的链接函数中获取transcludeFn,并将其链接到指令的作用域,可以实现这一点。

以下是一个示例代码,演示了如何解决这个问题:

angular.module('myApp').directive('myDirective', function($compile) {
  return {
    restrict: 'E',
    transclude: true,
    scope: {},
    template: '

Directive Content:

', link: function(scope, element, attrs, ctrl, transcludeFn) { transcludeFn(scope, function(clone) { element.append(clone); }); } }; });

在这个例子中,我们创建了一个名为myDirective的自定义指令。在指令的链接函数中,我们使用$compile服务手动链接被传递内容的作用域到指令的隔离作用域。通过调用transcludeFn并将其链接到指令的作用域,我们可以确保被传递的内容可以访问指令的作用域。

通过使用$compile服务手动链接被传递内容的作用域,我们可以解决指令内部无法访问父作用域的问题,从而增加指令的灵活性和可复用性。

0
0 Comments

在上述代码中,我们可以看到两个自定义的指令:state和city。state指令内部有一个controller函数,用来获取父级作用域的变量myName。city指令通过require属性将state指令作为依赖,并在link函数中获取state指令内部controller的方法getName()返回的值,并将其赋值给自己的作用域变量parentName。

这种情况下的问题是,当父级作用域的变量myName是一个可能会发生变化的数组时,在视图中不会实时更新。为了解决这个问题,可以使用$scope.$watch()来监听这个变量,当它发生变化时更新视图。

以下是修改后的代码:

var app = angular.module('myApp', []);
app.controller("CountryCtrl",function($scope){
    $scope.myName = "India";
});
app.controller("StateCtrl",function($scope){
});
app.directive("state",function(){return {
    restrict : 'E',
    transclude: true,
    scope : { myName  : '=nameofthestate'},
    template:"**   {{myName}} is inside {{$parent.myName}}",
    controller: function ($scope) {
        this.getName = function () {
            return $scope.myName;
        }
    }
}});
app.directive("city",function(){return {
    restrict : 'E',
    require:'^state',
    scope : { myName  : '=nameofthecity'},
    template:"****   {{myName}} is inside {{parentName}} which is in {{$parent.myName }} ",
    link: function(scope, element, attrs, ctrl) {
        scope.parentName = ctrl.getName();
        // 监听父级作用域的变量myName
        scope.$watch(function() {
            return scope.$parent.myName;
        }, function(newVal) {
            scope.parentName = newVal;
        });
    }
}});

在city指令的link函数中添加了一个$scope.$watch(),监听父级作用域的变量myName,并在变化时更新city指令的作用域变量parentName。

这样,当父级作用域的变量myName发生变化时,city指令的视图也会实时更新。

0
0 Comments

在AngularJS中,当自定义指令嵌套时,有时候子指令需要访问父指令的作用域。但是在一些情况下,子指令无法直接访问父指令的作用域,这就是问题“Custom child directive accessing scope of parent”出现的原因。

在给定的内容中,问题的原因是父指令的作用域是被传递的,它继承自控制器的作用域。这就是为什么$parent.MyName = India。此外,由于state指令的作用域是隔离的(scope = {} ),所以传递作用域的$parent是state指令的作用域。这就是为什么$parent.$parent.MyName = Tamilnadu。这是Angular 1.3更新的一部分。

解决这个问题的方法是使用transclude属性。当指令使用transclude: true时,它会创建一个新的“传递”子作用域,该作用域从父作用域继承。如果指令还创建了一个隔离作用域,传递作用域和隔离作用域将成为兄弟作用域。每个作用域的$parent属性引用同一个父作用域。

在Angular 1.3更新中,如果指令还创建了一个隔离作用域,传递作用域现在成为隔离作用域的子作用域。传递作用域和隔离作用域不再是兄弟作用域。传递作用域的$parent属性现在引用隔离作用域。

此外,Matthew的回答也提到了父子指令之间的通信问题。

0