Eu tenho dois controladores e compartilho dados entre eles com uma função app.factory.
O primeiro controlador adiciona um widget na matriz de modelo (pluginsDisplayed) quando um link é clicado. O widget é colocado na matriz e essa mudança é refletida na visualização (que usa ng-repeat para mostrar o conteúdo da matriz):
<div ng-repeat="pluginD in pluginsDisplayed">
<div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div>
</div>
O widget é baseado em três diretivas, k2plugin, remove e redimensiona. A diretiva remove adiciona um intervalo ao modelo da diretiva k2plugin. Quando a referida extensão é clicada, o elemento certo na matriz compartilhada é excluído com Array.splice()
. A matriz compartilhada é atualizada corretamente, mas a alteração não é refletida na visualização. No entanto, quando outro elemento é adicionado, após a remoção, a visualização é atualizada corretamente e o elemento excluído anteriormente não é mostrado.
O que estou entendendo de errado? Você poderia me explicar por que isso não funciona? Existe uma maneira melhor de fazer o que estou tentando fazer com o AngularJS?
Este é meu 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>
Este é meu 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);
})
};
});
fonte
Se você adicionar um
$scope.$apply();
direito depois$scope.pluginsDisplayed.splice(index,1);
, ele funciona.Não sei por que isso está acontecendo, mas basicamente quando o AngularJS não sabe que o $ escopo mudou, ele exige que você chame $ apply manualmente. Também sou novo no AngularJS, então não posso explicar isso melhor. Eu também preciso olhar mais para isso.
Eu encontrei este artigo incrível que explica isso muito bem. Observação: acho que pode ser melhor usar ng-click (docs) em vez de vincular a "mousedown". Eu escrevi um aplicativo simples aqui ( http://avinash.me/losh , fonte http://github.com/hardfire/losh ) baseado em AngularJS. Não é muito limpo, mas pode ajudar.
fonte
Eu tive o mesmo problema. O problema era porque 'ng-controller' foi definido duas vezes (no roteamento e também no HTML).
fonte
Remova "faixa por índice" do ng-repeat e isso atualizaria o DOM
fonte
Existe uma maneira fácil de fazer isso. Muito fácil. Desde que notei que
remove toda a lista de array $ scope.yourModel que você pode fazer assim
O $ scope.yourModel será atualizado com clonedObjects.
Espero que ajude.
fonte