Angularjs sai $ index sau orderBy


92

Tôi mới sử dụng Angular.js và gặp một số vấn đề khi sắp xếp mảng của mình và làm việc trên dữ liệu được sắp xếp đó.

Tôi có một danh sách với các mục và muốn sắp xếp nó theo "Store.storeName", danh sách này đang hoạt động cho đến nay. Nhưng sau khi sắp xếp dữ liệu, chức năng xóa của tôi không hoạt động nữa. Tôi nghĩ rằng đó là do $ index bị sai sau khi sắp xếp và vì vậy dữ liệu sai sẽ bị xóa.

Làm thế nào tôi có thể giải quyết điều đó? Sắp xếp thứ tự dữ liệu trong phạm vi và không trong chế độ xem? Làm thế nào để làm điều đó?

Đây là một số mã có liên quan:

Theo quan điểm:

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

Và trong bộ điều khiển của tôi, tôi có chức năng xóa này, chức năng này sẽ xóa dữ liệu cụ thể:

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

Điều này hoạt động tốt trước khi đặt hàng trong Chế độ xem. Nếu có điều gì quan trọng bị thiếu, xin vui lòng cho tôi bây giờ.

Cảm ơn!

Câu trả lời:


140

Thay vào đó hoặc chuyển tiếp trên $index- mà - như bạn đã nhận thấy - sẽ trỏ đến chỉ mục trong một mảng được sắp xếp / lọc, bạn có thể chuyển chính mục đó vào removeItemhàm của mình :

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

và sửa đổi removeItemhàm để tìm chỉ mục bằng cách sử dụng indexOfphương thức của một mảng như sau:

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

1
@ pkozlowski.opensource Bạn là một thiên tài! Bạn có thể vượt qua một mục, không phải chỉ mục .. Wow !! Cảm ơn anh bạn.
good_evening

Array indexOf không khả dụng trong Internet Explorer 8 trở xuống.
Peter Hedberg

4
Tiêu đề câu hỏi hỏi về $ index sai sau orderBy, câu trả lời này không giải quyết. Có những trường hợp bạn cần giá trị $ index chính xác (chẳng hạn như shift select trên danh sách). Làm cách nào để chúng tôi nhận được giá trị $ index chính xác sau khi áp dụng bộ lọc orderBy?
ClearCloud8

bạn cũng có thể tạo ra một mảng mới từ danh sách đặt hàng bên trong mẫu bằng cách làm một cái gì đó như thế này: "ele trong ordered_array = (mảng | lọc: lọc | orderBy: order_by)"
Porlune

Khéo léo! Cảm ơn nhé người anh em.
CENT1PEDE

23

Tôi bắt đầu tìm hiểu về góc cạnh và đối mặt với những rắc rối tương tự, và dựa trên câu trả lời của @ pkozlowski-opensource, tôi đã giải quyết nó chỉ bằng một số thứ như

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

1
Đây là tốt nhất và đơn giản như vậy chứ không phải là tạo bộ lọc tùy chỉnh vv .. 1
Rafique Mohammed

1
Làm thế nào đây không phải là câu trả lời chính xác? Điều này giải quyết vấn đề của tôi
Cyrus Zei

19

Tôi đã có cùng một vấn đề và các câu trả lời khác trong chủ đề này không phù hợp với tình huống của tôi.

Tôi đã giải quyết vấn đề của mình với bộ lọc tùy chỉnh:

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

có thể được sử dụng theo cách này:

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

và sau đó trong HTML, bạn có thể sử dụng item.indexthay thế $index.

Phương pháp này phù hợp với các tập hợp các đối tượng.

Vui lòng lưu ý rằng bộ lọc tùy chỉnh này phải là bộ lọc đầu tiên trong danh sách tất cả các bộ lọc được áp dụng (orderBy, v.v.) và nó sẽ thêm thuộc tính bổ sung index(tên có thể tùy chỉnh) vào từng đối tượng của bộ sưu tập.


Bạn có thể giải thích thêm về lý do tại sao các câu trả lời khác không phù hợp với hoàn cảnh của bạn?
pkozlowski.opensource

1
@ pkozlowski.opensource Cái này rõ ràng hơn nhiều. Cũng tùy thuộc vào những sự kiện nào có thể được đính kèm và độ phức tạp của các mục trong indexOf hiệu quả hơn nhiều. Cũng $scope.items.splice($scope.items.indexOf(item),1);sẽ không hoạt động như mong đợi đối với các mục trùng lặp.
martin

1
@martin, bạn nên sao lưu các tuyên bố của mình về hiệu suất bằng số thực. Một bộ lọc có khổng lồ bất lợi của đang được thực thi trên mỗi $ tiêu hóa chu kỳ vì vậy tôi không nghĩ rằng nó giúp với hiệu suất ...
pkozlowski.opensource

@ pkozlowski.opensource Điều đó đúng và nó chạy hai lần cho mỗi chu kỳ thông báo $. Điều quan trọng là "tùy thuộc vào những sự kiện nào có thể được đính kèm", hiệu suất quan trọng khi bạn không kiểm soát được tốc độ, ví dụ: sự kiện cuộn không điều chỉnh - trường hợp cực kỳ nghiêm trọng mà tôi biết.
martin

@mile Vâng, tôi có bản sao và đây là những gì tôi đang tìm kiếm, chỉ hơi buồn là Angular không theo dõi hoặc chỉ mục gốc trong một biến $. tôi đã thử (key, item) in itemsvà nó cũng không hoạt động. (chìa khóa không được giữ nguyên bản)
Rouche 23/12/15

4

Thử cái này:

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

}

Bạn có thể tìm thấy lời giải thích dài dòng trong mục này trong blog của tôi.


2

Trong trường hợp ai đó cần sử dụng $index, bạn có thể đặt tên cho mảng được sắp xếp / lọc:

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

Xem câu trả lời của tôi tại đây .


Tôi nghĩ câu trả lời này là ổn, nếu thiếu chi tiết. Tôi nghĩ hmk có nghĩa là khi danh sách được lọc đã được đặt sang một bên, như trên, chỉ mục có thể được sử dụng chống lại nó (tức là "sortedItems [$ index]") để truy xuất mục nhập mong muốn.
Jeremythuff

1

Tôi sẽ chỉ để lại một bình luận, nhưng tôi không có "danh tiếng".

giải pháp của dặm cũng chính xác là những gì tôi cần. Để trả lời câu hỏi của pkozlowski.opensource: khi bạn có các ngRepeats lồng nhau , một danh sách động (ví dụ: nơi bạn cho phép xóa) hoặc cả hai (đó là trường hợp của tôi), việc sử dụng $indexkhông hoạt động vì nó sẽ là chỉ mục sai cho back-end dữ liệu sau khi sắp xếp và sử dụng ngInitđể lưu vào bộ nhớ cache, giá trị cũng không hoạt động vì nó không được đánh giá lại khi danh sách thay đổi.

Lưu ý rằng giải pháp của mile cho phép tên thuộc tính chỉ mục đính kèm được tùy chỉnh bằng cách chuyển một tham số <tr ng-repeat="item in items | index:'originalPosition' | orderBy:'Store.storeName'">

Phiên bản đã chỉnh sửa của tôi:

.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 );
    });
})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.