【问题标题】:Nesting element directives can't access parent directive scope嵌套元素指令无法访问父指令范围
【发布时间】:2013-05-22 11:51:22
【问题描述】:

我已经为此苦苦挣扎了很长一段时间,但我不知道如何解决这个问题。

我正在尝试创建一个网格指令,其中包含用于描述网格的列指令,但列不会是元素,只会将列添加到在网格指令范围内声明的数组中。

我认为解释这个问题的最好方法是查看查看代码:

var myApp = angular.module('myApp', [])

    .controller('myCtrl', function ($scope, $http) {
    })
    .directive('mygrid', function () {
        return {
            restrict: "E",
            scope: true,
            compile: function ($scope) {
                debugger;
                $scope.Data = {};
                $scope.Data.currentPage = 1;
                $scope.Data.rowsPerPage = 10;
                $scope.Data.startPage = 1;
                $scope.Data.endPage = 5;
                $scope.Data.totalRecords = 0;
                $scope.Data.tableData = {};
                $scope.Data.columns = [];
            },
            replace: true,
            templateUrl: 'mygrid.html',
            transclude: true
        };
    })
    .directive('column', function () {
        return {
            restrict: "E",
            scope: true,
            controller: function ($scope) {
                debugger;
                $scope.Data.columns.push({
                    name: attrs.name
                });

            }
        };
    });

这里是 HTML 标记:

<body ng-app="myApp">
<div ng-controller="myCtrl">
    <input type="text" ng-model="filterGrid" />
    <mygrid>
        <column name="id">ID</column>
        <column name="name">Name</column>
        <column name="type">Type</column>
        <column name="created">Created</column>
        <column name="updated">Updated</column>
    </mygrid>
</div>

另外可以在jsfiddle中测试实际代码:http://jsfiddle.net/BarrCode/aNU5h/

我尝试使用编译、控制器和链接,但由于某种原因,父网格的列未定义。

我该如何解决这个问题?

编辑: 当我从 mygrid 指令中删除 replace、templateUrl、transclude 时,我可以从 column 指令中获取范围。

谢谢

【问题讨论】:

  • 这有什么成功吗?
  • 是的,在 angularJS 的更高版本中,您可以使用 $scope.$$childHead 获取父指令

标签: angularjs element angularjs-directive


【解决方案1】:

在更高版本的 AngularJS 中,我发现 $scope.$$childHead 可以满足我的要求。

它仍然是新的,但它也适用于具有隔离范围的指令。

所以在 Columns 指令中你可以这样做:

$scope.$$childHead.Data.columns.push({
                    name: attrs.name
                });

只需确保在网格编译后执行此命令即可。你可以这样做,但要在编译、链接和控制器之间切换,因为它们中的每一个都有不同的加载优先级。

【讨论】:

    【解决方案2】:

    我明白你想要做什么,但使用 column 指令可能不是解决问题的最佳方法。

    您正在尝试使用可自定义的列定义 grid 指令。每列都有 2 条相关信息:用于访问行数据中的值的键和要显示的标题。

    暂时忽略所有与分页相关的内容,这是解决问题的另一种方法。

    首先,让我们使用属性来定义列信息,所以我们的 HTML 如下所示:

    <body ng-app='app' ng-controller='Main'>
        <grid col-keys='id,name,type'
              col-titles='ID,Name,Type'
              rows='rows'>
        </grid>
    </body>
    

    对于 JS,我们显然需要 app 模块:

    var app = angular.module('app', []);
    

    这是grid 指令。它使用隔离作用域,但使用= 2-way 绑定从其父作用域获取行数据。请注意链接函数如何从attrs 对象中提取列信息。

    模板变得非常简单:循环列标题以定义标题,然后循环rows,并在每一行中循环列键。

    app.directive('grid', function() {
        return {
            restrict: 'E',
            scope: {
                rows: '='            
            },
            link: function(scope, element, attrs) {
                scope.colKeys = attrs.colKeys.split(',');
                scope.colTitles = attrs.colTitles.split(',');
            },
            replace: true,
            template:
                '<table>' +
                '  <thead>' +
                '    <tr>' +
                '      <th ng-repeat="title in colTitles">{{title}}</th>' +
                '    </tr>' +
                '  </thead>' +
                '  <tbody>' +
                '    <tr ng-repeat="row in rows">' +
                '      <td ng-repeat="key in colKeys">{{row[key]}}</td>' +
                '    </tr>' +
                '  </tbody>' +
                '</table>'
        };
    });
    

    还有一些示例数据可以开始使用。

    app.controller('Main', function($scope) {
        $scope.rows = [
            {id: 1, name: 'First', type: 'adjective'},
            {id: 2, name: 'Secondly', type: 'adverb'},
            {id: 3, name: 'Three', type: 'noun'}
        ];
    });
    

    Here it is in fiddle form.

    【讨论】:

    • 感谢您的解释,但我真的更愿意使用我的标记方式来解决这个问题,因为如果我想更改列顺序或向我拥有的列添加更多选项,请按照您的方式将它传递给网格中的另一个属性,它最终会看起来很长而且很乱。尝试简化标记方面的所有内容,并在指令方面做所有艰苦的工作。
    • 问题在于你将 JS 值编码到 HTML 中,这与使用 Angular 的目标背道而驰。请注意,我只是在这里使用字符串来简化事情。 colKeyscolTitles 可以通过类似 rows 的隔离范围引用并在父控制器中定义,避免“冗长而混乱”。
    【解决方案3】:

    正如伊姆里所说:

    在更高版本的 AngularJS 中,您可以使用 $scope.$$childHead 获取父指令

    我没有测试过。

    【讨论】:

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