2013-04-20 19 views
79

Sono nuovo in Angular.js e ho alcuni problemi nell'ordinare il mio array e lavorare su quei dati ordinati.

Ho una lista con gli articoli e voglio così ordinarla per "Store.storeName", che sta funzionando finora. Ma dopo aver ordinato i dati, la mia funzione di cancellazione non funziona più. Penso che questo sia perché l'indice $ è sbagliato dopo l'ordinamento, e quindi i dati errati vengono cancellati.

Come posso risolvere quello? Ordinare i dati nell'ambito e non nella vista? Come farlo?

Ecco codice rilevante:

Nella Vista:

<tr ng-repeat="item in items | orderBy:'Store.storeName'"> 
       <td><input class="toggle" type="checkbox" ng-model="item.Completed"></td> 
       <td>{{item.Name}}</td> 
       <td>{{item.Quantity}} Stk.</td> 
       <td>{{item.Price || 0 | number:2}} €</td>     
       <td>{{item.Quantity*item.Price|| 0 | number:2}} €</td> 
       <td>{{item.Store.storeName}}</td> 
       <td><a><img src="img/delete.png" ng-click="removeItem($index)">{{$index}}</a></td> 
      </tr> 

E nel mio controller ho questa funzione, che dovrebbe eliminare i dati specifici cancellare:

$scope.removeItem = function(index){ 
     $scope.items.splice(index,1); 
    } 

Questo funziona bene prima di ordinare nella vista. Se manca qualcosa di importante, per favore lasciatemi ora.

Grazie!

risposta

128

Invece o stabulazione sul $index - che - come avete notato - punterà l'indice in un array ordinato/filtrato, è possibile passare l'elemento stesso alla funzione removeItem:

<a><img src="img/delete.png" ng-click="removeItem(item)">{{$index}}</a> 

e modificare la funzione removeItem per trovare un indice utilizzando il metodo di una matrice indexOf come segue:

$scope.removeItem = function(item){ 
    $scope.items.splice($scope.items.indexOf(item),1); 
} 
+0

Wow grazie, funziona perfettamente! – FuzzBuzz

+1

@ pkozlowski.opensource Sei un genio! Puoi passare un oggetto, non indicizzare .. Wow !! Grazie uomo. –

+0

L'array indexOf non è disponibile in Internet Explorer 8 e versioni precedenti. –

3

Prova questo:

$scope.remove = function(subtask) { 

    var idx = $scope.subtasks.indexOf(subtask), 
     st = $scope.currentTask.subtasks[idx]; 

    // remove from DB 
    SubTask.remove({'subtaskId': subtask.id}); 

    // remove from local array 
    $scope.subtasks.splice(idx,1); 

} 

È possibile trovare spiegazioni dettagliate nello this entry nel mio blog.

+0

Voterebbe per la sola risposta di collegamento se potessi. – ankr

18

Ho avuto lo stesso problema e altre risposte in questo argomento non sono adatte alla mia situazione.

Ho risolto il mio problema con filtro personalizzato:

angular.module('utils', []).filter('index', function() { 
    return function (array, index) { 
     if (!index) 
      index = 'index'; 
     for (var i = 0; i < array.length; ++i) { 
      array[i][index] = i; 
     } 
     return array; 
    }; 
}); 

che può essere utilizzato in questo modo:

<tr ng-repeat="item in items | index | orderBy:'Store.storeName'"> 

e poi in HTML è possibile utilizzare al posto di item.index$index.

Questo metodo è adatto per le raccolte di oggetti.

Si prega di prendere in considerazione che questo filtro personalizzato dovrebbe essere il primo nell'elenco di tutti i filtri applicati (orderBy ecc.) E aggiungerà la proprietà aggiuntiva index (il nome è personalizzabile) in ogni oggetto del collezione.

+0

Potresti approfondire il motivo per cui le altre risposte non sono adatte alla tua situazione? –

+1

@ pkozlowski.opensource Questo è molto più pulito. Inoltre, dipende da quali eventi potrebbero essere allegati e dalla complessità degli elementi di indexOf molto più efficienti. Anche '$ scope.items.splice ($ scope.items.indexOf (item), 1);' non funzionerà come previsto per gli elementi duplicati. – martin

+1

@martin dovresti eseguire il backup delle tue affermazioni relative alle prestazioni con numeri reali. Un filtro ha uno svantaggio _huge_ di essere eseguito su _each e ogni_ $ ciclo di digest, quindi non credo che aiuti le prestazioni ... –

1

Avrei appena lasciato un commento, ma non ho la "reputazione".

soluzione di miglio è esattamente quello che mi serviva anche io. Per rispondere a pkozlowski.La domanda di opensource: quando hai nidificato ngRepeat s, un elenco dinamico (ad esempio dove permetti le rimozioni), o entrambi (che è il mio caso), usando $index non funziona perché sarà l'indice sbagliato per i dati di back-end dopo l'ordinamento e l'uso di ngInit per memorizzare nella cache il valore non funziona perché non viene rivalutato quando l'elenco cambia.

nota che la soluzione di miglio permette il nome della proprietà di indice collegato a essere personalizzato passando un parametro <tr ng-repeat="item in items | index:'originalPosition' | orderBy:'Store.storeName'">

La mia versione ottimizzato:

.filter('repeatIndex', function repeatIndex() 
{ 
// This filter must be called AFTER 'filter'ing 
// and BEFORE 'orderBy' to be useful. 
    return(function(array, index_name) 
    { 
     index_name = index_name || 'index'; 
     array.forEach(function(each, i) 
     {each[ index_name ] = i;}); 
     return(array); 
    }); 
}) 
15

ho iniziato a imparare angolare e affrontato problemi simili, e sulla base sulla risposta di @ pkozlowski-opensource, ho risolto solo con qualcosa di simile

<a> 
    <img src="img/delete.png" ng-click="removeItem(items.indexOf(item))"> 
    {{items.indexOf(item)}} 
</a> 
+0

Questo è il migliore e così semplice piuttosto che creare un filtro personalizzato ecc. +1 –

+0

come non è questa la risposta corretta? Questo ha risolto il mio problema –

-2

Nel caso in cui qualcuno ha bisogno di usare 0.123., si può dare un nome alla array ordinato/filtrato:

<tr ng-repeat="item in sortedItems = (items | orderBy:'Store.storeName') track by $index"> 

vedi la mia risposta here.

Problemi correlati