在Angular中结合使用父控制器数据和隔离范围

时间:2015-01-05 04:23:39

标签: angularjs angularjs-directive angularjs-scope

首先是代码,然后是解释:

的index.html

<!DOCTYPE html>
<html>

<head>
<script data-require="angular.js@*" data-semver="1.3.7" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.7/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="app.js"></script>
</head>

<body ng-app="myApp">
<div ng-controller="myCtrl">
    <my-directive data="1" />
    <my-directive data="2" />
</div>
</body>

</html>

app.js

angular.module("myApp", []).directive("myDirective", function ($parent) {
  return {
      restrict: "E",
      scope: {
          data: "@",
      },
      template: function(element, attrs){
        switch(attrs.data){
          case '1':
            return '<h3>'+ $parent.stringForDirective1 + '</h3>';
          case '2':
            return '<h3>'+ $parent.stringForDirective2 + '</h3>';
        }
      }
  };
}).controller('myCtrl',function($scope){
$scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
$scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
});

现在解释一下。如果我要设置范围:false&#39;在我的指令中,当指令位于其范围内时,我可以轻松访问控制器的数据。但是,根据我的理解,为了使用带有自定义指令的HTML属性中的任何值,必须将整个指令放入隔离的范围。

我想使用HTML属性返回使用父控制器数据的模板。

使用&#39;范围时,如何获得控制器数据的好处:false&#39;能够传递自定义HTML属性吗?

$ parent示例不起作用,我只是添加它以显示我一直在考虑解决方案的方式,我认为它清楚地显示了我的意图。

2 个答案:

答案 0 :(得分:0)

不确定为什么要注入$parent依赖项。我希望那只是你用来表明你如何思考的那个:The $parent example does not work, I simply added it to show the way I've been thinking towards a solution, and I think it shows my intent clearly.


无论如何,你不需要任何这些。为了使它全部工作,只需去掉那个依赖,不要将父范围值连接到模板中,但让Angular在编译模板后使用它来处理它(使用双花括号进行绑定):

switch(attrs.data){
      case '1':
        return '<h3>{{$parent.stringForDirective1}}</h3>';
      case '2':
        return '<h3>{{$parent.stringForDirective2}}</h3>';
    }

那仍然会寻找scope.$parent,这就是你想要的。

请参阅此处的完整工作示例http://plnkr.co/edit/pW5G2Yy4SelW5DxKBMqW?p=preview

或者在这里,作为一个代码段

angular.module("myApp", [])
  .directive("myDirective", function() {
    return {
      restrict: "E",
      scope: {
        data: "@",
      },
      template: function(element, attrs) {
        switch (attrs.data) {
          case '1':
            return '<h3>{{$parent.stringForDirective1}}</h3>';
          case '2':
            return '<h3>{{$parent.stringForDirective2}}</h3>';
        }
      }
    };
  })
  .controller('myCtrl', function($scope) {
    $scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
    $scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="myApp">
  <div ng-controller="myCtrl">
    <my-directive data="1"></my-directive>
    <my-directive data="2"></my-directive>
  </div>
</body>


注意:必须指定指令结束标记,因为速记版本只读取第一个指令(Plunker表示指令元素上不允许使用尾随固相),请参见此处:http://plnkr.co/edit/Qt0z0poU0ogoQq4C9a3n?p=preview

答案 1 :(得分:-1)

指令可以有三种可能的范围模式:

  1. 隔离范围(范围:{})
  2. 子范围(范围:true)
  3. 继承范围(范围:false)
  4. 根据您的指令的需要,这些范围模式中的任何一个都是有效的。

    如果要创建具有隔离范围的指令,则可以通过元素的属性将模型传递到指令的隔离范围:

    scope: {
        modelA: '=', // model binding
        modelB: '@', // string binding
        modelC: '&'  // method binding in parent scope
    }
    

    属性

    <div directive model-a="user" model-b="hello {{ user.name }}" model-c="addUser(user)"></div>
    

    示例(不是理想的指令实现,但是为了展示如何通过属性将模型传递给隔离的范围)

    angular.module("myApp", []).directive("myDirective", function ($parent) {
      return {
          restrict: "E",
          scope: {
              data: "@",
              stringForDirective1: '=?',
              stringForDirective2: '=?'
          },
          template: '<h3 ng-if="data = '1'">{{stringForDirective1 }}</h3><h3 ng-if="data = '2'">{{stringForDirective2 }}</h3>'
    
      };
    }).controller('myCtrl',function($scope){
    $scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
    $scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
    });
    

    HTML

    <body ng-app="myApp">
    <div ng-controller="myCtrl">
        <my-directive data="1" string-for-directive1="stringForDirective1" />
        <my-directive data="2" string-for-directive2="stringForDirective2" />
    </div>
    </body>