2015-04-29 7 views
15

Mam tablicę przedmiotów, która jest wyświetlana w tabeli przy użyciu polecenia ng-repeat. Po kliknięciu elementu element ten jest pobierany z serwera, a tabela powinna zostać zaktualizowana o zaktualizowany element.Jak mogę zamienić obiekt w tablicy wyświetlanej za pomocą polecenia ng-repeat?

Function, aby uzyskać zaktualizowany element po kliknięciu pozycji w tabeli:

$scope.getUpdatedItem = function(item){ 
    itemService.getItem(item).then(
     function(updatedItem){ 
      item = updatedItem; 
     }, 
     function(error){ 
      //Handle error 
     } 
    ); 
}; 

ja wyświetlania elementów za pomocą:

<tr ng-repeat="item in myItems"> 

problemu: pozycja w tabeli nigdy nie zaktualizowany.

Jaki jest najlepszy sposób aktualizacji elementu w powtórzeniu ng? Czy mogę użyć "track by $ index" w ng-repeat? Czy muszę iterować nad myItems, aby znaleźć element, który chcę zastąpić?

Aktualizacja:

Możliwym rozwiązaniem jest zamiast używać

item = updatedItem,

używać:

var index = $scope.myItems.indexOf(item); 
$scope.myItems[index] = updateItem; 

Jednak czuję, że nie powinno być "czystsze" sposób robienia tego.

+0

Co 'itemService' loook jak? – tymeJV

+0

wygląda na to, że potrzebujesz zmiennej w kontrolerze, którą możesz ustawić na podstawie danych w 'updatedItem'. Kiedy działa 'item = updatedItem', zasięg' item' jest właśnie tą funkcją. – jcuenod

+0

Czy istnieje jedna lub dwie tabele? Jeden z listą przedmiotów i jeden dla wybranego przedmiotu? – Eloims

Odpowiedz

14

Nie ma o wiele czystszego sposobu (wtedy twoja aktualizacja). Jak zauważyłeś, po zmianie item w funkcji zwrotnej zmieniasz lokalne odwołanie, a nie oryginalny element w tablicy.

Można poprawić ten kawałek za pomocą $index z ng-repeat, zamiast obliczania to sam:

<div ng-click="getUpdatedItem(item, $index)"> </div> 

A w kontrolerze:

$scope.getUpdatedItem = function(item, index){ 
    itemService.getItem(item).then(
    function(updatedItem){ 
     $scope.myItems[index] = updateItem; 
    }, 
    function(error){ 
     //Handle error 
    } 
    ); 
}; 

Można również użyć angular.copy zamiast ale jest znacznie mniej wydajny:

function(updatedItem){ 
    angular.copy(updateItem, item); 
}, 
+0

Użycie $ należy unikać, ponieważ jest to indeks wielokrotności powtórzeń, a nie rzeczywisty indeks tablicy obiektu zasięgu, który jest powiązany z widokiem; Czasami może to pójść okropnie źle w przypadku sortowania lub filtrowania, na przykład masz tablicę bird [0] = papuga; ptak [1] = wrona; jeśli filtrujesz dla wrony, twoja siatka spowoduje $ index = 0, ale w rzeczywistości wrona była na indeksie 1. – user1697113

2

Jeśli rozumiem problem właściwie

mógł coś takiego pracy?

<!-- 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; 
    }); 
}; 
+0

To może nie działać ze względu na zakres 'ng-repeat'. Obserwuje jedynie zmiany samego obiektu, a nie jego właściwości. – Asta

+0

Myślę, że gdy jakakolwiek obietnica $ q zostanie rozwiązana, cały zakres zostanie ponownie sprawdzony rekurencyjnie – Eloims

+0

Twoje jedyne uaktualnienie właściwości '$ scope.items' zamiast zmiany jego wartości. ng-repeat ma tylko płytki zegarek, a nie głęboki zegarek, więc nie zobaczy, że te właściwości się zmieniły. – Asta

1

item może rozpocząć się jako odniesienie do pozycji na liście, ale kiedy mówisz:

item = updatedItem; 

można osadzić że wiążąca - nie jesteś już odnosząc się do pozycji na liście, ale do odłączonego, który został zwrócony w twojej obietnicy. Albo trzeba będzie zmodyfikować element, tak jak poniżej:

function(updatedItem){ 
    item.varA = updatedItem.varA 
    item.varB = updatedItem.varB 
    ... 
} 

Lub, jeśli robi się zbyt owłosione, można rozważyć szereg artykuł, który wygląda mniej więcej tak:

var items = [ 
    { data: item1 }, 
    { data: item2 }, 
    { data: item3 } 
}; 

W tym momencie Twój funkcja aktualizacji będzie wyglądać następująco:

function(updatedItem){ 
    item.data = updatedItem; 
}, 
0

Właśnie spędziłem godziny w tej sprawie. Nie mogłem użyć rozwiązania $index z @eladcon, ponieważ mój ng-repeat również użył filtra, indeks nie jest poprawny, jeśli wiersze/elementy są filtrowane.

myślałem, że będę mógł po prostu to zrobić:

$filter('filter')($scope.rows, {id: 1})[0] = newItem; 

ale to nie działa.

Skończyłem iterować tablicę, aż znalazłem dopasowanie, a następnie używając $index z iteracji (nie z ng-repeat), aby ustawić element tablicy na nowy element.

// i'm looking to replace/update where id = 1 
angular.forEach($scope.rows, function(row, $index) { 
    if (row.id === 1) { 
    $scope.rows[$index] = newItem; 
    } 
}) 

Zobacz tutaj: https://codepen.io/anon/pen/NpVwoq?editors=0011

Powiązane problemy