Chức năng sắp xếp tùy chỉnh trong ng-repeat


113

Tôi có một tập hợp các ô hiển thị một số nhất định tùy thuộc vào tùy chọn nào được người dùng chọn. Bây giờ tôi muốn thực hiện sắp xếp theo bất kỳ số nào được hiển thị.

Đoạn mã dưới đây cho thấy cách tôi đã triển khai nó (bằng cách gettting / đặt một giá trị trong phạm vi thẻ mẹ). Bây giờ, vì hàm orderBy nhận một chuỗi, tôi đã cố gắng đặt một biến trong phạm vi thẻ có tên là curOptionValue và sắp xếp theo đó, nhưng nó dường như không hoạt động.

Vì vậy, câu hỏi trở thành, làm thế nào để tôi tạo một chức năng sắp xếp tùy chỉnh?

<div ng-controller="aggViewport" >
<div class="btn-group" >
    <button ng-click="setOption(opt.name)" ng-repeat="opt in optList" class="btn active">{{opt.name}}</button>
</div>
<div id="container" iso-grid width="500px" height="500px">
    <div ng-repeat="card in cards" class="item {{card.class}}" ng-controller="aggCardController">
        <table width="100%">
            <tr>
                <td align="center">
                    <h4>{{card.name}}</h4>
                </td>
            </tr>
            <tr>
                <td align="center"><h2>{{getOption()}}</h2></td>
            </tr>
        </table>        
    </div>
</div>

và bộ điều khiển:

module.controller('aggViewport',['$scope','$location',function($scope,$location) {
    $scope.cards = [
        {name: card1, values: {opt1: 9, opt2: 10}},
        {name: card1, values: {opt1: 9, opt2: 10}}
    ];

    $scope.option = "opt1";

    $scope.setOption = function(val){
        $scope.option = val;
    }

}]);

module.controller('aggCardController',['$scope',function($scope){
    $scope.getOption = function(){
        return $scope.card.values[$scope.option];
    }
}]);

Câu trả lời:


192

Trên thực tế, orderBybộ lọc có thể nhận như một tham số không chỉ là một chuỗi mà còn là một hàm. Từ orderBytài liệu: https://docs.angularjs.org/api/ng/filter/orderBy ):

function: Hàm Getter. Kết quả của hàm này sẽ được sắp xếp bằng cách sử dụng toán tử <, =,>.

Vì vậy, bạn có thể viết hàm của riêng mình. Ví dụ: nếu bạn muốn so sánh các thẻ dựa trên tổng của opt1 và opt2 (tôi đang làm điều này, vấn đề là bạn có thể có bất kỳ chức năng tùy ý nào), bạn sẽ viết vào bộ điều khiển của mình:

$scope.myValueFunction = function(card) {
   return card.values.opt1 + card.values.opt2;
};

và sau đó, trong mẫu của bạn:

ng-repeat="card in cards | orderBy:myValueFunction"

Đây là jsFiddle đang hoạt động

Điều đáng chú ý khác là đó orderBychỉ là một ví dụ về bộ lọc AngularJS, vì vậy nếu bạn cần một hành vi sắp xếp cụ thể, bạn có thể viết bộ lọc của riêng mình (mặc dù orderByphải đủ cho hầu hết các trường hợp sử dụng).


Điều đó thật tuyệt, nhưng liệu có thể tạo bộ lọc cho điều đó không?
hugo der hungrige

Có, nó vẫn đang hoạt động. Đây là phiên bản cập nhật
jahller

Tại sao không có mô tả về nhiều tham số trong tài liệu ?? BTW: Cảm ơn, nó hoạt động. :)
mayankcpdixit

Bạn có biết làm thế nào tôi có thể xử lý nhiều tiêu chí với cách tiếp cận này không? Làm cách nào để trả về nhiều giá trị từ myValueFunction?
akcasoy

26

Giải pháp được chấp nhận chỉ hoạt động trên mảng chứ không phải đối tượng hoặc mảng liên kết. Thật không may, vì Angular phụ thuộc vào việc triển khai JavaScript của kiểu liệt kê mảng, thứ tự của các thuộc tính đối tượng không thể được kiểm soát một cách nhất quán. Một số trình duyệt có thể lặp lại qua các thuộc tính đối tượng theo từ điển, nhưng điều này không thể được đảm bảo.

Ví dụ: Đưa ra bài tập sau:

$scope.cards = {
  "card2": {
    values: {
      opt1: 9,
      opt2: 12
    }
  },
  "card1": {
    values: {
      opt1: 9,
      opt2: 11
    }
  }
};

và chỉ thị <ul ng-repeat="(key, card) in cards | orderBy:myValueFunction">, ng-repeat có thể lặp lại "card1" trước "card2", bất kể thứ tự sắp xếp.

Để giải quyết vấn đề này, chúng ta có thể tạo một bộ lọc tùy chỉnh để chuyển đổi đối tượng thành một mảng, sau đó áp dụng chức năng sắp xếp tùy chỉnh trước khi trả về bộ sưu tập.

myApp.filter('orderByValue', function () {
  // custom value function for sorting
  function myValueFunction(card) {
    return card.values.opt1 + card.values.opt2;
  }

  return function (obj) {
    var array = [];
    Object.keys(obj).forEach(function (key) {
      // inject key into each object so we can refer to it from the template
      obj[key].name = key;
      array.push(obj[key]);
    });
    // apply a custom sorting function
    array.sort(function (a, b) {
      return myValueFunction(b) - myValueFunction(a);
    });
    return array;
  };
});

Chúng tôi không thể lặp lại các cặp (khóa, giá trị) kết hợp với các bộ lọc tùy chỉnh (vì các khóa cho mảng là các chỉ mục số), do đó, mẫu phải được cập nhật để tham chiếu đến các tên khóa được chèn.

<ul ng-repeat="card in cards | orderByValue">
    <li>{{card.name}} {{value(card)}}</li>
</ul>

Đây là một fiddle đang hoạt động bằng cách sử dụng bộ lọc tùy chỉnh trên một mảng kết hợp: http://jsfiddle.net/av1mLpqx/1/

Tham khảo: https://github.com/angular/angular.js/issues/1286#issuecomment-22193332


1
Tôi biết tôi không nên nhưng tôi chỉ cần - Cảm ơn.
Elia Weiss

7

Liên kết sau giải thích các bộ lọc trong Angular rất tốt. Nó chỉ ra cách có thể xác định logic sắp xếp tùy chỉnh trong một ng-repeat. http://toddmotto.com/everything-about-custom-filters-in-angular-js

Để sắp xếp đối tượng có thuộc tính, đây là mã tôi đã sử dụng: (Lưu ý rằng sắp xếp này là phương pháp sắp xếp tiêu chuẩn của JavaScript và không dành riêng cho góc cạnh) Tên cột là tên của thuộc tính mà việc sắp xếp sẽ được thực hiện.

self.myArray.sort(function(itemA, itemB) {
    if (self.sortOrder === "ASC") {
        return itemA[columnName] > itemB[columnName];
    } else {
        return itemA[columnName] < itemB[columnName];
    }
});

0

Để bao gồm hướng cùng với hàm orderBy:

ng-repeat="card in cards | orderBy:myOrderbyFunction():defaultSortDirection"

Ở đâu

defaultSortDirection = 0; // 0 = Ascending, 1 = Descending

emmmmm, tôi chỉ nghĩ rằng bạn đã viết myOrderbyFunction()thay vì bạn sẽ viết myOrderbyFunctionmà không có (), nó được gọi cho mỗi cặp phần tử để bạn cung cấp phân loại tùy chỉnh.
Victor
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.