orderBy 후 Angularjs가 잘못된 $ index


92

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

이것은보기에서 주문하기 전에 잘 작동합니다. 중요한 것이 없으면 지금 알려주십시오.

감사!

답변:


140

대신 또는 $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);
}

1
@ pkozlowski.opensource 당신은 천재입니다! 색인이 아닌 항목을 전달할 수 있습니다. 와우 !! 고마워요.
good_evening 2014-08-12

배열 indexOf는 Internet Explorer 8 이하에서 사용할 수 없습니다.
Peter Hedberg 2014 년

4
질문 제목은 orderBy 이후에 잘못된 $ index에 대해 묻고 있으며,이 답변은이를 다루지 않습니다. 올바른 $ index 값이 필요한 경우가 있습니다 (예 : 목록에서 시프트 선택). orderBy 필터가 적용된 후 올바른 $ index 값을 어떻게 얻습니까?
ClearCloud8 2016-10-26

다음과 같이하여 템플릿 내의 정렬 된 목록에서 새 배열을 만들 수도 있습니다. "ele in ordered_array = (array | filter : filter | orderBy : order_by)"
Porlune

산뜻한! 감사합니다 형제.
CENT1PEDE

23

나는 각도를 배우기 시작했고 비슷한 문제에 직면했고 @ pkozlowski-opensource의 대답을 바탕으로 다음과 같은 것으로 해결했습니다.

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

1
이 .. 최고의 오히려 사용자 정의 필터 등을 만드는 것보다 너무 간단 한
Rafique 모하메드

1
이것이 정답이 아닌 이유는 무엇입니까? 이것은 내 문제 해결
사이러스 Zei을

19

나는 같은 문제가 있었고이 주제의 다른 답변은 내 상황에 적합하지 않습니다.

사용자 지정 필터로 문제를 해결했습니다.

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컬렉션의 각 개체에 추가 속성 (이름은 사용자 지정할 수 있음)을 추가합니다 .


다른 답변이 귀하의 상황에 적합하지 않은 이유에 대해 자세히 설명해 주시겠습니까?
pkozlowski.opensource

1
@ pkozlowski.opensource 이것은 훨씬 더 깨끗합니다. 또한 어떤 이벤트가 첨부 될 수 있는지에 따라 indexOf의 항목이 훨씬 더 효율적입니다. 또한 $scope.items.splice($scope.items.indexOf(item),1);중복 항목에 대해 예상대로 작동하지 않습니다.
martin 2014

1
@martin 성능에 대한 주장을 실수로 뒷받침해야합니다. 필터는이 거대한 에서 실행되는 단점 각각의 모든 ... 나는 그것이 성능에 도움이 생각하지 않도록 $ 사이클을 소화
pkozlowski.opensource

@ pkozlowski.opensource 맞습니다. $ digest주기마다 두 번 실행됩니다. 중요한 것은 "첨부 할 수있는 이벤트에 따라"이며, 속도를 제어 할 수 없을 때 성능이 중요합니다 (예 : 조절되지 않은 스크롤 이벤트-제가 아는 극단적 인 경우).
martin

@mile 글쎄, 나는 중복이 있고 이것은 내가 찾던 것입니다 .Angular가 $ 변수의 원래 색인이나 추적을 유지하지 않는다는 것이 조금 슬픈 일입니다. 나는 시도했지만 (key, item) in items작동하지 않습니다. (키는 원본에 보관되지 않음)
Rouche

4

이 시도:

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

}

내 블로그 의이 항목 에서 자세한 설명을 찾을 수 있습니다 .


2

누군가가 사용해야 $index하는 경우 정렬 / 필터링 된 배열에 이름을 지정할 수 있습니다.

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

여기 내 대답을 참조 하십시오 .


세부 사항이 부족하면이 대답이 괜찮다고 생각합니다. hmk가 의미하는 바는 위와 같이 필터링 된 목록을 따로 설정하면 원하는 항목을 검색하기 위해 인덱스 (예 : "sortedItems [$ index]")를 사용할 수 있다는 것입니다.
Jeremythuff dec

1

그냥 코멘트를 남겼을 텐데 "평판"이 없어요.

마일의 솔루션은 나에게도 필요한 것입니다. pkozlowski.opensource의 질문에 대답하려면 : 중첩 된 ngRepeats, 동적 목록 (예 : 제거를 허용하는 위치) 또는 둘 다 (내 경우) $index가 있으면 백엔드에 대한 잘못된 인덱스가 될 것이므로 사용 이 작동하지 않습니다. 정렬 및 ngInit캐시에 사용한 데이터 는 목록이 변경 될 때 재평가되지 않기 때문에 작동하지 않습니다.

마일의 솔루션은 매개 변수를 전달하여 첨부 된 색인 속성 이름을 사용자 정의 할 수 있도록합니다. <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 );
    });
})
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.