J'ai un tableau d'éléments qui est affiché dans une table en utilisant ng-repeat. Lorsque vous cliquez sur un élément, cet élément est extrait du serveur et la table doit ensuite être mise à jour avec l'élément mis à jour.
Fonction pour obtenir l'élément mis à jour en cliquant sur un élément de la table:
$scope.getUpdatedItem = function(item){
itemService.getItem(item).then(
function(updatedItem){
item = updatedItem;
},
function(error){
//Handle error
}
);
};
J'affiche les éléments en utilisant:
<tr ng-repeat="item in myItems">
Le problème: l'élément de la table n'est jamais mis à jour.
Quel est le meilleur moyen de mettre à jour l'élément dans le ng-repeat? Puis-je utiliser "track by $ index" dans le ng-repeat pour cela? Ou dois-je parcourir mes éléments pour trouver l'élément que je souhaite remplacer?
Mettre à jour:
Une solution possible est au lieu d'utiliser
item = updatedItem,
utiliser:
var index = $scope.myItems.indexOf(item);
$scope.myItems[index] = updateItem;
Cependant, j'estime qu'il devrait y avoir une façon "plus propre" de procéder.
Comme vous l'avez remarqué, lorsque vous modifiez la variable item
dans votre fonction de rappel, vous modifiez la référence locale et non l'élément d'origine du tableau.
Vous pouvez un peu améliorer cela en utilisant le $index
à partir du ng-repeat
, au lieu de le calculer vous-même:
<div ng-click="getUpdatedItem(item, $index)"> </div>
Et dans votre contrôleur:
$scope.getUpdatedItem = function(item, index){
itemService.getItem(item).then(
function(updatedItem){
$scope.myItems[index] = updateItem;
},
function(error){
//Handle error
}
);
};
Vous pouvez aussi utiliser angular.copy
à la place mais c'est beaucoup moins efficace:
function(updatedItem){
angular.copy(updateItem, item);
},
Si je comprends bien votre problème
quelque chose comme ça pourrait-il fonctionner?
<!-- template code -->
<table>
...
<tr ng-repeat="(index, item) in items">
<td>{{item.name}}</td>
<td>
{{item.detail}}
<button ng-if="!item.detail" ng-click="loadItem(index)">
</td>
</tr>
</table>
// Controller Code
$scope.items = [...]
$scope.loadItem = function(index){
itemService.getItemDetail($scope.items[index]).then(function(itemDetail){
$scope.items[index].detail = itemDetail;
});
};
item
peut commencer comme référence à un élément de votre liste, mais lorsque vous dites:
item = updatedItem;
Vous remettez en place cette liaison - vous ne faites plus référence à l'élément de la liste, mais à l'élément déconnecté qui a été renvoyé dans votre promesse. Soit vous devrez modifier l’article, comme ceci:
function(updatedItem){
item.varA = updatedItem.varA
item.varB = updatedItem.varB
...
}
Ou, si cela devient trop poilu, vous pourriez envisager un tableau d'éléments qui ressemble davantage à ceci:
var items = [
{ data: item1 },
{ data: item2 },
{ data: item3 }
};
A quel point votre fonction de mise à jour ressemblera à ceci:
function(updatedItem){
item.data = updatedItem;
},
Je viens de passer des heures sur cette question. Je ne pouvais pas utiliser la solution $index
de @eladcon, car mon ng-repeat
utilisait également un filtre; l'index n'est pas correct si les lignes/éléments sont filtrés.
Je pensais pouvoir faire ceci:
$filter('filter')($scope.rows, {id: 1})[0] = newItem;
mais ça ne marche pas.
J'ai fini par itérer le tableau jusqu'à trouver une correspondance, puis à l'aide du $index
de l'itération (et non du ng-repeat
) pour définir l'élément de tableau sur le nouvel élément.
// i'm looking to replace/update where id = 1
angular.forEach($scope.rows, function(row, $index) {
if (row.id === 1) {
$scope.rows[$index] = newItem;
}
})