【问题标题】:Custom child directive accessing scope of parent自定义子指令访问父级的范围
【发布时间】:2015-09-20 22:43:48
【问题描述】:

我的 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

谁能告诉我我在这里做错了什么?

【问题讨论】:

  • 对不起,你的小提琴不适合我。
  • stackoverflow.com/questions/23437113/… 这可能会帮助你看起来像你想做的事情
  • 您可以使用transclude : 'element' 进行自定义嵌入。构造函数在link : function(scope, element, attrs, Ctlr, transclude){} 中可用

标签: javascript angularjs angularjs-directive angularjs-scope


【解决方案1】:

city 指令 $parent 是 state 指令的嵌入范围。

state 指令的嵌入范围是继承为 state 指令的 $parent 的,它是控制器,因此这就是 $parent.MyName = India 的原因。

嵌入范围的 $parent 是状态指令隔离范围 (scope = {} ),这就是为什么 $parent.$parent.MyName = Tamilnadu (Angular 1.3 更新的一部分)

发生的事情的一些细节: How to access parent scope from within a custom directive *with own scope* in AngularJS?

transclude: true - 指令创建一个新的“transcluded”子 作用域,其原型继承自父作用域。如果 指令还创建了一个隔离范围、嵌入的和 隔离范围是兄弟。每个作用域的 $parent 属性 引用相同的父范围。

Angular v1.3 更新:如果指令还创建了一个隔离范围, 嵌入范围现在是隔离范围的子级。这 嵌入和隔离范围不再是兄弟。 $父母 转入作用域的属性现在引用了隔离作用域。

对于父子指令通信,Matthew 的回答也是正确的。

【讨论】:

    【解决方案2】:

    这对你有用吗?改编自this answer

    没有一种直接的方法可以访问转入内容的父元素,因此我们将父控制器注入到子元素中以访问其范围。

      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();
          }
      }});
    

    【讨论】:

    • 是的。有用。但我接受@kwan245 的回答,因为它解释了我犯了什么错误.. :) 谢谢 Metthew
    • 我使用了这种方法,但在我的例子中,保存名称的变量是一个可能会改变的数组。有没有办法处理这种情况,因为在这种情况下视图不会为我更新?我知道我可以使用手表,但希望尽可能避免这种情况。我这里有一个例子:stackoverflow.com/questions/42676713/…
    【解决方案3】:

    当 AngularJS 遇到 transclude 时,它​​会克隆之前的 HTML 将其替换为模板或 templateUrl 内容。那么,当它 遇到 ng-transclude ,它会编译转入的内容,但是 将其链接到父范围而不是孤立范围 指示。因此,嵌入的内容仍然可以访问 父控制器及其内容,而指令 HTML 有一个 隔离范围(或新范围,视情况而定)。

    AngularJS 启动并运行

    【讨论】:

      【解决方案4】:

      查看我的指令的解决方案,它适用于很多父母。我所做的是删除 transclude 并需要参数。不用管脏 html,看 js,简单到 f.. :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
          };
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-27
        • 1970-01-01
        • 2014-10-25
        相关资源
        最近更新 更多