【问题标题】:AngularJS : Directive Isolated ScopingAngularJS:指令隔离范围
【发布时间】:2014-07-08 17:03:31
【问题描述】:

我正在开发一个表格形式的 AngularJS 指令。父级大多数控件ng-table 需要为其选项和模型具有隔离范围。

但是,子级应该“继承”该范围,这样您就不必将大量选项传递给相互关联的组件组。

例如:

 <div ng-table="tableOptions" ng-model="results">

    <div ng-table-header>
        <div ng-table-header-column="column" 
             ng-repeat="column in tableOptions.columns">
            {{column.name}}
        </div>
    </div>

    <div ng-table-body>

        <div ng-table-row="row"
             ng-repeat="row in $results">

            <div ng-table-cell="column"
                 ng-repeat="column in tableOptions.columns">

                {{row[column.id]}}

            </div>
        </div>

    </div>
    <div ng-table-footer></div>
</div>

在上面的例子中,ng-table-headerng-header-column等都需要访问父控件ng-table的属性。此外,所有指令replacetransclude

我知道我可以将 broadcast 事件传递给子/父指令,但是有没有更好的方法来限制父级的范围并将其自动传递给子级?

【问题讨论】:

  • 将 ng-table 定义为具有独立作用域(作用域:{}),并让子指令具有子作用域(作用域:true)。这样,子指令将继承范围变量,一直到隔离的父范围。
  • 请注意:Angular 文档建议避免使用 ng- 前缀作为专有指令的前缀,因为如果他们推出自己的 ng-table 实现,您可能会遇到问题。最好在那里使用你自己的前缀......

标签: angularjs angularjs-directive angularjs-scope


【解决方案1】:

哦,伙计,你强迫我看看表单和输入指令是如何在 Angular 中实现的。

因此,angularjs 与您想要实现的功能相似——带有 ng-inputng-form 指令。

当您使用formng-form 指令时,它会创建控制器(指令可以做到)并且transclude html-code 会继承它。 ng-input(input) 在require 选项中要求它。

require: ['ngModel', '^?form', '^?ngModelOptions'],

所以你在link 函数中得到了这个控制器。所以...你可以调用函数,做一些事情,你知道的。

你可以这样做(只是一个想法,这就是它的工作原理):

.directive('coolTable', function() {
  return {
    ...
    controller: function($scope) {
        $scope.columns = [];  /* Here you will have all table columns, so you can send it's data to service and do any work */
        $scope.registerColumn = function(column) {
            $scope.columns.push(column);
        };
    },
    ...
  };
})


.directive('column', function() {
  return {
    ...
    require: '^?coolTable',
    ...
    link: function(scope, element, attrs, coolTable) {
        coolTable.registerColumn(this);
    },
  };
})


<coolTable>
    <column></column>
    <column></column>
    <column></column>
</coolTable>

【讨论】:

  • 你能扩展registerColumn方法的用法吗?
  • 这取决于你。您可以在控制器中收集列指令或仅收集列名,您可以从指令中触发表的“sortBy”或执行其他任何操作!
  • angular.extend 在寄存器中如何将表范围道具复制到列...或至少在这方面的东西
  • 看,如我所见(你可以指出我错的地方),你想让列能够修改数据,例如按this列排序,按@987654332搜索@ 柱子。或在分页上翻页点击table-footer。所有这些功能都可以轻松归档,就像指令和表格本身之间的“对话”一样。从列,你应该调用表的orderBy,从页脚,你应该调用表的goTo。您可以在 table 指令的控制器中定义所有这些方法。所以,没有理由继承它。但你可以做任何你想做的事,你也可以有好主意!
【解决方案2】:

我能够找到一个解决方法来查看创建自己的 transclude 指令以应用范围的 angular-ui 代码。

所以我的主 table 指令开始如下:

module.directive('ngTable', function ($rootScope, $timeout, $window, $compile) {
    return {
        restrict: 'AE',
        transclude: true, // NOTE THIS
        replace: true, // NOTE THIS
        templateUrl: 'common/components/table/views/table.tpl.html',
        scope: {
            ngModel: "=",
            tableOptions: "=ngTable"
        },
        controller: 'ngTableCtrl',
        link: function ($scope, $element, $attributes, controller, ngModel) {
            ....
        }
     }
});

然后我创建自己的 transclude 指令,例如:

module.directive('tableTransclude', function () {
    return {
        link: function ($scope, $element, $attrs, controller, $transclude) {
            $transclude($scope, function (clone) {
                $element.empty();
                $element.append(clone);
            });
        }
    };
})

表格模板中的用法如下:

<div table-transclude />

然后马上!!!有点hacky,但可以完成工作。我理解 Angular 为什么这样做,但在某些情况下,您需要这种类型的范围。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-08
    • 1970-01-01
    • 2012-12-27
    • 2019-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多