J'ai deux contrôleurs et partage des données entre eux avec une fonction app.factory.
Le premier contrôleur ajoute un widget dans le tableau de modèles (pluginsDisplayed) lorsqu'un lien est cliqué. Le widget est poussé dans le tableau et ce changement est reflété dans la vue (qui utilise ng-repeat pour afficher le contenu du tableau):
<div ng-repeat="pluginD in pluginsDisplayed">
<div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div>
</div>
Le widget est construit sur trois directives, k2plugin, remove et resize. La directive remove ajoute une étendue au modèle de la directive k2plugin. Lorsque ledit span est cliqué, l'élément de droite dans le tableau partagé est supprimé avec Array.splice()
. Le tableau partagé est correctement mis à jour, mais la modification n'est pas reflétée dans la vue. Cependant, lorsqu'un autre élément est ajouté, après la suppression, la vue est correctement actualisée et l'élément précédemment supprimé n'est pas affiché.
Qu'est-ce que je me trompe? Pouvez-vous m'expliquer pourquoi cela ne fonctionne pas? Existe-t-il une meilleure façon de faire ce que j'essaie de faire avec AngularJS?
Ceci est mon 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>
C'est mon 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);
})
};
});
la source
Si vous ajoutez un
$scope.$apply();
droit après,$scope.pluginsDisplayed.splice(index,1);
cela fonctionne.Je ne sais pas pourquoi cela se produit, mais fondamentalement, lorsque AngularJS ne sait pas que la portée $ a changé, il doit appeler $ apply manuellement. Je suis également nouveau sur AngularJS, je ne peux donc pas l'expliquer mieux. J'ai besoin de me pencher davantage dessus.
J'ai trouvé cet article génial qui l'explique assez correctement. Remarque: je pense qu'il serait peut-être préférable d'utiliser ng-click (docs) plutôt que de lier à "mousedown". J'ai écrit une application simple ici ( http://avinash.me/losh , source http://github.com/hardfire/losh ) basée sur AngularJS. Ce n'est pas très propre, mais cela pourrait être utile.
la source
J'ai eu le même problème. Le problème était que 'ng-controller' était défini deux fois (dans le routage et aussi dans le HTML).
la source
Supprimez "track by index" du ng-repeat et cela rafraîchirait le DOM
la source
Il existe un moyen simple de le faire. Très facile. Depuis que j'ai remarqué que
supprime toute la liste de tableaux $ scope.yourModel que vous pouvez faire comme ceci
Le $ scope.yourModel sera mis à jour avec les clonedObjects.
J'espère que cela pourra aider.
la source