双向绑定不在ng-repeat内更新

时间:2013-10-28 16:34:50

标签: javascript angularjs

我在ng-repeat中遇到双向绑定问题。当你从列表中选择一种颜色时,我希望触发下面的$ watch。

$scope.$watch('favoriteColors', function (newValue) {
    console.log('example-favoriteColors', newValue);
});

我希望Orange$scope.favoriteColors检查时显示。

示例:http://plnkr.co/edit/k5SEQw4XFnxriD2I8ZG7?p=preview

directive('checkBox', function () {
    return {
        replace: true,
        restrict: 'E',
        //require: '^ngModel',
        scope: {
            'externalValue': '=ngModel',
            'value': '&'
        },
        template: function (el, attrs) {
            var html =
                '<div class="ngCheckBox">'+
                    '<span ng-class="{checked: isChecked}">' +
                        '<input type="checkbox" ng-model="isChecked"/>'+
                    '</span>'+
                '</div>';
            return html;
        },
        controller: ['$scope', '$timeout', function ($scope, $timeout) {
            var initialized = false;
            console.log($scope.value());
            if (angular.isArray($scope.externalValue)) {
                $scope.isChecked = $scope.externalValue.indexOf($scope.value()) > 0;
            } else {
                $scope.isChecked = !!$scope.externalValue;
            }

            $scope.$watch('isChecked', function (newValue) {
                if (angular.isDefined(newValue)) {
                    //add or remove items if this is an array
                    if (angular.isArray($scope.externalValue)) {
                        var index = $scope.externalValue.indexOf($scope.value());
                        if(index > -1) {
                            $scope.externalValue.splice(index, 1);
                        } else if (initialized) {
                            $scope.externalValue.push($scope.value());
                        }
                    } else {
                        //simple boolean value
                        $scope.externalValue = newValue;
                    }
                    if (initialized)
                        console.log($scope.externalValue);
                }
            });

            $timeout(function () {
                initialized = true;
            });
        }],
        link: function (scope, el, attrs) {

        }
    };
});

3 个答案:

答案 0 :(得分:2)

请查看此插件:http://plnkr.co/edit/pbHz4ohBPi7iYq6uJI8X?p=preview

有很多变化。其中一些是:

  • 模板不一定是函数,因为它是静态的。
  • 不需要initialized(因此$timeout)。
  • 我实现了自己的indexOf功能; ==意义上的对象有可能不同,但在x.name === y.name意义上等于; (虽然我对此有些怀疑)
  • add or remove items if this is an array部分错了;您需要根据isChecked的值更新数组,而不是基于项目是否已存在于数组中indexOf)。
  • favoriteColors初始化为数组,而不是单个对象,以保持一致,即$scope.favoriteColors = [$scope.colors[1]];
  • (次要)在favoriteColors更改时添加了更多描述性日志。
  • 使用$watch("favoriteColors", function() {...}, true)来监视数组内的更改(而不是true最后一个参数)。

答案 1 :(得分:0)

我认为这是因为您需要在对象而不是平面数组上引用属性。传递像数组一样的原始数据结构时,它会通过引用传递,因此更新不会正确传递。 (Post by Mark Rajcok.

我继续前进并通过一点点攻击你的傻瓜来证明这一点。我将$scope.favoriteColors = $scope.colors[1];更改为$scope.favoriteColors = {value:$scope.colors[1]};并将<check-box ng-model="favoriteColors" value="color">更改为<check-box ng-model="favoriteColors.value" value="color">

Plunkr

您可以在plunkr中看到,当您点击复选框时,console.log语句现在在$watch函数下发生。

答案 2 :(得分:0)

我看到你正在使用angular-form-ui's checkbox directive

  • 使用$watchCollectionlink to documentation)而不是$watch来观看数组的更改
  • $scope.favoriteColors初始化为包含应检查的值的数组

我已将您的更改还原为angular-form-ui.js,因为这些更改违反了指令。它们现在与latest commit on Github (checkbox.js)中显示的代码完全相同。只有一件事发生了变化,angular-form-ui模块的初始化是通过将[]作为第一行的第二个参数添加的。

以下是更新的plunker:http://plnkr.co/edit/mlUt46?p=preview