0

我正在尝试为类似于高级组合框的东西编写指令,我从骨架开始并遇到了一些问题。

以下是指令的代码:

/* Controller */
function MyCtrl($scope) {
    $scope.bigListSelectedItem = 0;
    $scope.bigComboItems = [
        {value: 'item1 value', label: 'Item 1 label'}, 
        {value: 'item2 value', label: 'Item 2 label'}, 
        {value: 'item3 value', label: 'Item 3 label'}
    ];

    $scope.addBigComboItem = function () {
        $scope.bigComboItems.push({value: 'new item', label: 'Item 1 label'});
    };

    $scope.removeBigComboItem = function () {
        console.log('removing');
        $scope.bigComboItems.splice($scope.bigComboItems.length - 1, 1);

    };
}

MyCtrl.$inject = ['$scope'];

/* Services*/
var services = angular.module('myApp', [])
    .directive('bigCombo', function () {
        return {
            restrict: 'C',
            transclude: true,
            scope: true,
            controller: function ($scope, $element, $attrs) {
                $scope.items = [];
                this.addItem = function (item) {
                    $scope.items.push(item);
                };

                this.removeItem = function (item) {
                    for (var i = 0; i < $scope.items.length; i++) {
                        if ($scope.items[i] === item) {
                            $scope.items.splice(i, 1);
                            break;
                        }
                    }
                };

                $scope.selectItem = function(item) {
                    $scope.selectedItem =  item;
                };
            },

            template:
                '<div>' +
                    '<div>Selected Item {{selectedItem.value}}</div>' +
                    '<ul class="">' +
                        '<li ng-repeat="item in items">' +
                            '<a ng-click="selectItem(item)">{{item.value}}</a>' +
                        '</li>' +
                    '</ul>' +
                    '<div ng-transclude></div>' +
                '</div>',

            replace: true

        };
    }).
    directive('bigComboItem', function() {
        return {
            require: '^bigCombo',
            restrict: 'C',
            scope: { 
                value: '@'
            },

            link: function(scope, element, attrs, controller) {
                controller.addItem(scope);
                scope.$on('$destroy', function () {
                    controller.removeItem(scope);
                });
            }
        };
    });

你可以在这里看到它运行:http: //jsfiddle.net/HP5tQ/

如您所见,外部“bigCombo”指令等待“bigComboItem”指令调用其“addItem”函数。这很好用。但是,如果我删除其中一个项目,视图将不会更新,直到(至少这是我怀疑的)下一个 $digest 发生。

在上面的示例中,单击“删除项目”将从数组中删除最后一个项目,这将导致 ng-repeat 从 DOM 中删除它的“bigComboItem”指令,这将发出一个“$destory”事件,该事件将调用“ bigCombo 的“removeItem”功能。'removeItem' 然后将删除它,但视图不会更新,除非我从数组中添加/删除另一个项目,或者在范围上强制 $digest。

任何想法我在这里做错了什么?

4

1 回答 1

2

只需在监听器上使用 $timeout (在指令定义中注入它:

scope.$on('$destroy', function (ev) {
    $timeout(function() { controller.removeItem(scope); });
});

这将确保removeItem在 $apply 块内调用 。这种方法的好处是 1. 如果您已经在 $apply 块中,则不会发生任何不同 2. 如果有 $apply 已调度,则该函数将放在已调度块的末尾 3. 否则, $digest 将尽快安排,其中包含函数。

所以这是双赢的:)

于 2013-06-05T11:43:04.770 回答