У меня есть два контроллера, и я делюсь данными между ними с помощью функции app.factory.
Первый контроллер добавляет виджет в массив модели (pluginsDisplayed) при нажатии ссылки. Виджет помещается в массив, и это изменение отражается в представлении (которое использует ng-repeat для отображения содержимого массива):
<div ng-repeat="pluginD in pluginsDisplayed">
<div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div>
</div>
Виджет построен на трех директивах: k2plugin, remove и resize. Директива remove добавляет диапазон к шаблону директивы k2plugin. При щелчке по указанному диапазону правый элемент в общем массиве удаляется с помощью Array.splice()
. Общий массив обновлен правильно, но изменение не отражается в представлении. Однако при добавлении другого элемента после удаления представление обновляется правильно, а ранее удаленный элемент не отображается.
Что я ошибаюсь? Не могли бы вы объяснить мне, почему это не работает? Есть ли лучший способ сделать то, что я пытаюсь сделать, с помощью AngularJS?
Это мой 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>
Это мой 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);
})
};
});
источник
Если вы добавите
$scope.$apply();
сразу после,$scope.pluginsDisplayed.splice(index,1);
то он работает.Я не уверен, почему это происходит, но в основном, когда AngularJS не знает, что область $ изменилась, он требует вручную вызвать $ apply. Я также новичок в AngularJS, поэтому не могу объяснить это лучше. Мне тоже нужно больше разобраться в этом.
Я нашел эту замечательную статью, в которой это объясняется достаточно хорошо. Примечание: я думаю, что было бы лучше использовать ng-click (docs) вместо привязки к "mousedown". Я написал здесь простое приложение ( http://avinash.me/losh , источник http://github.com/hardfire/losh ) на основе AngularJS. Это не очень чисто, но может помочь.
источник
Я была такая же проблема. Проблема заключалась в том, что ng-controller был определен дважды (в маршрутизации, а также в HTML).
источник
Удалите «трек по индексу» из ng-repeat, и он обновит DOM
источник
Есть простой способ сделать это. Очень просто. Поскольку я заметил, что
удаляет весь список массивов $ scope.yourModel, который вы можете сделать следующим образом
В $ scope.yourModel будут добавлены клонированные объекты.
Надеюсь, это поможет.
источник