2015-07-03 118 views
40

我在我的angularJS应用程序中有两个自定义指令。一个作为父母,另一个作为孩子。我正在尝试访问子指令内的父级范围。但我没有得到所需的输出。自定义子级指令访问父级的范围

<div ng-controller="CountryCtrl"> 
{{myName}} 
    <div ng-controller="StateCtrl"> 
     <state nameofthestate="'Tamilnadu'"> 
      <city nameofthecity="'Chennai'"></city> 
     </state> 
    </div> 
</div> 

和我的脚本看起来像

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}}<br/><ng-transclude></ng-transclude>" 
}}); 
app.directive("city",function(){return { 
    restrict : 'E', 
    require:'^state', 
    scope : { myName : '=nameofthecity'}, 
    template:"**** {{myName}} is inside {{$parent.myName}} which is in {{$parent.$parent.myName }}<br/> " 
}}); 

相应的jsfiddle提供https://jsbin.com/nozuri/edit?html,js,output

的输出,我得到是

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

和预期输出是

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

任何人都可以教我在这里做错了吗?

+0

对不起,但你的小提琴不适合我。 –

+1

嗨http://stackoverflow.com/questions/23437113/get-property-value-from-parent-directive-within-child-directive这可能会帮助你它看起来像你想要做的 –

+1

你可以做一个自定义transclude与'transclude:'element''。构造函数在'link:function(scope,element,attrs,Ctlr,transclude){}' – gr3g

回答

28

城市指令$ parent是一个跨状态的州指令范围。

状态指令的transcluded作用域继承了$ parent作为控制器的state指令,因此这就是为什么$ parent.MyName = India。

transcluded范围的$父是状态指令分离范围(范围= {}),这就是为什么$母体。$ parent.MyName =塔米尔纳杜(角1.3更新的部分)

enter image description here

什么细节位发生: How to access parent scope from within a custom directive *with own scope* in AngularJS?

transclude:真 - 指令创建一个新的“transcluded”孩子 范围,这prototypically从父范围继承。如果 指令也创建隔离范围,则隔行范围和隔行范围是兄弟。每个作用域 的$ parent属性引用相同的父作用域。

Angular v1.3更新:如果该指令还创建隔离范围 ,则该transcluded范围现在是隔离范围的子级。跨越和隔离范围不再是兄弟姐妹。 transcluded作用域的$ parent 属性现在引用隔离作用域。

另外Matthew的回答对于亲子指导沟通是正确的。

15

这是否适合您?改编自this answer

有没有一种简单的方式来访问transcluded内容的父元素,所以我们注入父控制器到子访问其范围。

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}}<br/><ng-transclude></ng-transclude>", 
     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 }}<br/> ", 
     link: function(scope, element, attrs, ctrl) { 
     scope.parentName = ctrl.getName(); 
     } 
    }}); 
+1

yes中可用。有用。但我接受@ kwan245的答案,因为它解释了我做了什么错误.. :)感谢Metthew –

+0

我已经使用这种方法,但在我的情况下,变量持有名称是一个可能会改变的数组。有没有办法处理这种情况,因为在这种情况下,对于我来说视图不会更新? 我知道我可以使用手表,但希望尽可能避免这种情况。我有一个例子: http://stackoverflow.com/questions/42676713/sharing-data-between-child-directives/42677394 –

3

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

AngularJS并运行

1

看看我的指令sollution,它与很多parrents的。我所做的是去除跨界并需要参数。不要为脏兮兮的html而烦恼,只是看js,简单点就是:D

CRM.directive('inputwv', function ($compile) { 
    var getTemplate = function(contentType) { 
     var template = ''; 

     switch(contentType) { 
       case '3': 
        template = '<input type="number" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px;width:100px">' 
        break; 
       case '0': 
        template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">' 
        break; 
       case '1': 
        template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">' 
        break; 
       case '2': 
        template = '<textarea class="materialize-textarea teal-text" type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">' 
        break; 
       case '4': 
        template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">' 
        break; 
       case '5': 
        template = '<input type="date" class="datepicker" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px"><script type="text/javascript">$(\'.datepicker\').pickadate({selectMonths: true, selectYears: 15});</script>' 
        break; 
       default: 
        template = '<textarea class="materialize-textarea teal-text" type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">' 
      } 

     return template; 
} 

    var linker = function(scope, element, attrs) { 
     element.html(getTemplate(attrs.typ)).show(); 

     $compile(element.contents())(scope); 
    } 

    return { 
     restrict: "E", 
     link: linker 
    }; 
}); 
相关问题