web-dev-qa-db-ja.com

AngularjsがorderByの後の誤った$ index

私はAngular.jsを初めて使用しますが、配列の並べ替えとその並べ替えられたデータの操作に問題があります。

私はアイテムのリストを持っているので、今のところ機能している「Store.storeName」でソートします。しかし、データをソートした後、私の削除機能はもう機能していません。ソート後に$ indexが間違っているため、間違ったデータが削除されるためだと思います。

どうすれば解決できますか?ビューではなくスコープ内のデータを注文しますか?どうやってするか?

関連するコードは次のとおりです。

ビューで:

<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>

そして、私のコントローラーにはこの削除機能があり、特定のデータを削除する必要があります。

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

これは、ビューで注文する前にうまく機能します。重要なものが不足している場合は、今私に教えてください。

ありがとう!

90
FuzzBuzz

代わりに、または$index-お気づきのように-ソート/フィルターされた配列のインデックスを指すので、アイテム自体をremoveItem関数に渡すことができます。

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

removeItem関数を変更して、次のように配列のindexOfメソッドを使用してインデックスを検索します。

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

私はangular=を学び始め、同様のトラブルに直面し、@ pkozlowski-opensourceの答えに基づいて、

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

私は同じ問題を抱えており、このトピックの他の回答は私の状況には適していません。

カスタムフィルターの問題を解決しました。

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;
    };
});

この方法で使用できます:

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

hTMLでは、item.indexの代わりに$indexを使用できます。

このメソッドは、オブジェクトのコレクションに適しています。

このカスタムフィルターは、適用されるすべてのフィルター(orderByなど)のリストの最初のものである必要があり、追加のプロパティindex(名前はカスタマイズ可能)を各オブジェクトに追加することを考慮してくださいコレクション。

19
mile

これを試して:

$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);

}

詳細な説明は、私のブログの このエントリ にあります。

4
Dimitry

私はコメントを残したが、「評判」はありません。

マイルのソリューションはまさに私が必要としていたものです。 pkozlowski.opensourceの質問に答えるには、ネストされたngRepeats、動的リスト(例:削除を許可する場所)、またはその両方(私の場合)を使用している場合、$indexを使用しても動作しませんリストの変更時に再評価されないため、並べ替えてngInitを使用して値をキャッシュした後は、バックエンドデータの間違ったインデックスになります。

Mileのソリューションでは、パラメーター<tr ng-repeat="item in items | index:'originalPosition' | orderBy:'Store.storeName'">を渡すことにより、添付のインデックスプロパティ名をカスタマイズできることに注意してください。

私の微調整バージョン:

.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 );
    });
})
1
MarkMYoung

誰かが$indexを使用する必要がある場合、ソート/フィルターされた配列に名前を付けることができます:

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

私の答えをご覧ください こちら

1
hmk