0

我在 AngularJS 中有一个指令,它可以像这样获取一个数组:

var current_element_list = scope.$apply($(this).attr('sortable-model'));

其余代码如下所示:

//in the controller
$scope.project.elements = [];

//in the html
<customDirective sortable-model='project.elements'>

我认为 scope.$apply 会返回对$scope.project.elements数组的引用,因此我在指令中所做的任何更改都将保留在该模型中。但是,情况似乎并非如此,因为我对数组所做的任何更改都没有保存。无论如何,我可以从这里通过sortable-model属性获得的更改保存回根范围内的数组吗?

4

3 回答 3

1

您需要设置一个隔离范围并将您的模型值映射到指令中的本地值。

从 Angularjs 指令范围文档中:

= 或 =attr - 在本地范围属性和通过 attr 属性值定义的 name 的父范围属性之间建立双向绑定。如果未指定 attr 名称,则假定属性名称与本地名称相同。给定范围的widget定义:{localModel:'=myAttr'},那么widget范围属性localModel将在父范围上反映parentModel的值。对 parentModel 的任何更改都将反映在 localModel 中,而对 localModel 的任何更改都将反映在 parentModel 中。

angular("app")
  .directive('customDirective ', function () {
   return {
       restrict: 'E',
       link: function (scope, element, attrs) {
           scope.localModel.push("New Element");
       }, 
       scope:{
           localModel: '=sortableModel',
       }
   }
});
于 2013-07-31T22:21:24.427 回答
1

当您想要在指令和控制器范围之间进行双向绑定时,您应该scope在定义指令时使用该属性。

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

app.controller("Ctrl", function ($scope) {
    $scope.project = {
        elements: [1, 2, 3]
    };
});

app.directive("customDirective", function () {
    return {
        restrict: "E",
        scope: {
            sortableModel: "="
        },
        link: function (scope, element, attrs) {
            // Access the controller's scope.project.elements here as scope.sortableModel
            console.log(scope.sortableModel);

            // Changes to scope.sortableModel will also affect the controller's scope.project.elements
            scope.sortableModel.push(4);
        }
    };
});

看到一个工作中的小提琴

于 2013-07-31T22:19:40.800 回答
1

回答你的问题

由于标准原型继承规则适用,因此将指令中数组的更改反映在原始文件中应该可以工作。当您执行此操作时,您的指令中的含义(即使它创建了一个新范围):

current_element_list[0] = 'new value';

这种变化应该反映在控制器的$scope.project.elements变量中。

现在,如果您的指令没有创建新范围,则scope传递给指令的变量应该与$scope包含控制器的变量相同,这意味着您应该能够随意更改该范围内的任何内容。因此,如果您在指令中执行此操作:

scope.project.elements = ['new value'];

这种变化也应该反映在控制器的$scope.project.elements变量中。

如果您的指令创建了一个隔离范围,那么您不应该使用它scope.$apply($(this).attr('sortable-model'))来获取属性的评估值。相反,您将使用:

scope : {
    current_element_list : '=sortableModel'
}

这会为 sortableModel 的评估值创建一个双向数据绑定,并且现在可以通过scope.current_element_list.


对代码的建议改进

关于这条线:

var current_element_list = scope.$apply($(this).attr('sortable-model'));

如果您只是想“获取”数组,则不需要 use $apply,而是使用$eval. 该$apply函数主要用于将一个人带回 AngularJS 上下文,触发摘要循环并检查所有模型是否平衡并且所有更改都被考虑在内。$eval$apply函数调用)简单地评估给定范围内的给定表达式。

此外,使用指令,您永远不必使用 jQuery 来获取属性名称或值,甚至是元素本身。链接函数获得了 4 个参数,其中一个是具有所述元素的属性和属性值的对象。指令的控制器也可以注入 $attrs 服务,这将返回相同的内容。(阅读指令文档)

这是上面的代码重做:

link : function(scope, element, attrs, controllers) {
    // ...
    var current_element_list = scope.$eval(attrs['sortable-model']);
    // ...
}
于 2013-07-31T22:38:54.333 回答