AngularJS:从模型数组拼接模型元素时,ng-repeat 列表不更新 [英] AngularJS: ng-repeat list is not updated when a model element is spliced from the model array

查看:21
本文介绍了AngularJS:从模型数组拼接模型元素时,ng-repeat 列表不更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个控制器,并使用 app.factory 函数在它们之间共享数据.

当点击链接时,第一个控制器在模型数组 (pluginsDisplayed) 中添加一个小部件.小部件被推送到数组中,此更改反映到视图中(使用 ng-repeat 显示数组内容):

<div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div>

小部件建立在三个指令之上,k2plugin、remove 和 resize.remove 指令向 k2plugin 指令的模板添加一个跨度.当点击所述跨度时,使用Array.splice()删除共享数组中的右侧元素.共享数组已正确更新,但更改反映在视图中.但是,当添加另一个元素时,删除后,视图会正确刷新,并且不会显示之前删除的元素.

我哪里错了?你能解释一下为什么这不起作用吗?有没有更好的方法来做我想要用 AngularJS 做的事情?

这是我的 index.html:

<头><script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"><script src="main.js"></script><身体><div ng-app="livePlugins"><div ng-controller="pluginlistctrl"><span>添加 {{pluginList.length}} 个插件之一</span><li ng-repeat="plugin in pluginList"><span><a href="" ng-click="add()">{{plugin.name}}</a></span>

<div ng-controller="k2ctrl"><div ng-repeat="pluginD in pluginsDisplayed"><div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div>

</html>

这是我的 main.js:

var app = angular.module ("livePlugins",[]);app.factory('数据', 函数 () {返回 {pluginsDisplayed: []};});app.controller ("pluginlistctrl", function ($scope, Data) {$scope.pluginList = [{name: "plugin1"}, {name:"plugin2"}, {name:"plugin3"}];$scope.add = 函数 () {console.log ("调用添加", this.plugin.name, this.pluginList);var newPlugin = {};newPlugin.id = this.plugin.name + '_' + (new Date()).getTime();newPlugin.name = this.plugin.name;Data.pluginsDisplayed.push (newPlugin);}})app.controller ("k2ctrl", function ($scope, Data) {$scope.pluginsDisplayed = Data.pluginsDisplayed;$scope.remove = 函数(元素){console.log ("调用删除", this.pluginid, element);var len = $scope.pluginsDisplayed.length;无功指数 = -1;//查找数组中的元素for (var i = 0; i 

解决方案

每当您在 AngularJS 之外进行某种形式的操作时,例如使用 jQuery 进行 Ajax 调用,或者将事件绑定到您需要的元素上时让 AngularJS 知道更新自己.这是您需要执行的代码更改:

app.directive("remove", function () {返回函数(范围、元素、属性){element.bind(鼠标按下",函数(){范围.删除(元素);范围.$应用();})};});app.directive("resize", function () {返回函数(范围、元素、属性){element.bind(鼠标按下",函数(){范围.调整大小(元素);范围.$应用();})};});

这是关于它的文档:https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply

I have two controllers and share data between them with an app.factory function.

The first controller adds a widget in the model array (pluginsDisplayed) when a link is clicked. The widget is pushed into the array and this change is reflected into the view (that uses ng-repeat to show the array content):

<div ng-repeat="pluginD in pluginsDisplayed">
    <div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div>
</div>

The widget is built upon three directives, k2plugin, remove and resize. The remove directive adds a span to the template of the k2plugin directive. When said span is clicked, the right element into the shared array is deleted with Array.splice(). The shared array is correctly updated, but the change is not reflected in the view. However, when another element is added, after the remove, the view is refreshed correctly and the previously-deleted element is not shown.

What am I getting wrong? Could you explain me why this doesn't work? Is there a better way to do what I'm trying to do with AngularJS?

This is my index.html:

<!doctype html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js">
        </script>
        <script src="main.js"></script>
    </head>
    <body>
        <div ng-app="livePlugins">
            <div ng-controller="pluginlistctrl">
                <span>Add one of {{pluginList.length}} plugins</span>
                <li ng-repeat="plugin in pluginList">
                    <span><a href="" ng-click="add()">{{plugin.name}}</a></span>
                </li>
            </div>
            <div ng-controller="k2ctrl">
                <div ng-repeat="pluginD in pluginsDisplayed">
                    <div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div>
                </div>
            </div>
        </div>
    </body>
</html>

This is my main.js:

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

app.factory('Data', function () {
    return {pluginsDisplayed: []};
});

app.controller ("pluginlistctrl", function ($scope, Data) {
    $scope.pluginList = [{name: "plugin1"}, {name:"plugin2"}, {name:"plugin3"}];
    $scope.add = function () {
        console.log ("Called add on", this.plugin.name, this.pluginList);
        var newPlugin = {};
        newPlugin.id = this.plugin.name + '_'  + (new Date()).getTime();
        newPlugin.name = this.plugin.name;
        Data.pluginsDisplayed.push (newPlugin);
    }
})

app.controller ("k2ctrl", function ($scope, Data) {
    $scope.pluginsDisplayed = Data.pluginsDisplayed;

    $scope.remove = function (element) {
        console.log ("Called remove on ", this.pluginid, element);

        var len = $scope.pluginsDisplayed.length;
        var index = -1;

        // Find the element in the array
        for (var i = 0; i < len; i += 1) {
            if ($scope.pluginsDisplayed[i].id === this.pluginid) {
                index = i;
                break;
            }
        }

        // Remove the element
        if (index !== -1) {
            console.log ("removing the element from the array, index: ", index);
            $scope.pluginsDisplayed.splice(index,1);
        }

    }
    $scope.resize = function () {
        console.log ("Called resize on ", this.pluginid);
    }
})

app.directive("k2plugin", function () {
    return {
        restrict: "A",
        scope: true,
        link: function (scope, elements, attrs) {
            console.log ("creating plugin");

            // This won't work immediately. Attribute pluginname will be undefined
            // as soon as this is called.
            scope.pluginname = "Loading...";
            scope.pluginid = attrs.pluginid;

            // Observe changes to interpolated attribute
            attrs.$observe('pluginname', function(value) {
                console.log('pluginname has changed value to ' + value);
                scope.pluginname = attrs.pluginname;
            });

            // Observe changes to interpolated attribute
            attrs.$observe('pluginid', function(value) {
                console.log('pluginid has changed value to ' + value);
                scope.pluginid = attrs.pluginid;
            });
        },
        template: "<div>{{pluginname}} <span resize>_</span> <span remove>X</span>" +
                       "<div>Plugin DIV</div>" +
                  "</div>",
        replace: true
    };
});

app.directive("remove", function () {
    return function (scope, element, attrs) {
        element.bind ("mousedown", function () {
            scope.remove(element);
        })
    };

});

app.directive("resize", function () {
    return function (scope, element, attrs) {
        element.bind ("mousedown", function () {
            scope.resize(element);
        })
    };
});

解决方案

Whenever you do some form of operation outside of AngularJS, such as doing an Ajax call with jQuery, or binding an event to an element like you have here you need to let AngularJS know to update itself. Here is the code change you need to do:

app.directive("remove", function () {
    return function (scope, element, attrs) {
        element.bind ("mousedown", function () {
            scope.remove(element);
            scope.$apply();
        })
    };

});

app.directive("resize", function () {
    return function (scope, element, attrs) {
        element.bind ("mousedown", function () {
            scope.resize(element);
            scope.$apply();
        })
    };
});

Here is the documentation on it: https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply

这篇关于AngularJS:从模型数组拼接模型元素时,ng-repeat 列表不更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆