programing

빈 필드를 사용하여 AngularJS 오더바이

mytipbox 2023. 2. 27. 23:24
반응형

빈 필드를 사용하여 AngularJS 오더바이

데이터를 주문하고 일부 필드가 비어 있거나 값이 없는 경우를 제외하고 모든 수정 작업을 수행합니다.순서가 정해지면 이 빈 필드가 먼저 나타납니다.예를 들어, 숫자를 정렬할 때 "0" 값을 얻기 전에 큰 빈 목록이 표시됩니다.

이렇게 하고 있습니다.

ng-click="predicate = 'name'; reverse=!reverse"

그리고.

ng-repeat="name in names | orderBy:predicate:reverse"

JSFiddle:http://jsfiddle.net/JZuCX/1/

이것을 쉽게 고칠 수 있는 우아한 방법이 있을까요?무슨 일이 있어도 빈 들판이 꼴찌가 됐으면 좋겠어요.

문자열 정렬은 다음과 같습니다.

item in (items|orderBy:['!name', 'name'])

장점은 (좀 더 간결하다는 것 말고도) 정렬되어 있다는 것입니다.null&undefined빈 끈을 가지고.

제 경우 공백과 늘과 정의되지 않은 것을 맨 위에 함께 표시(기본적으로 늘과 정의되지 않은 것을 맨 아래 정렬)하고 싶었기 때문에 다음을 사용했습니다.

item in (items|orderBy:['!!name', 'name'])

정렬된 배열에서 이름이 비어 있는 항목을 가져와 끝에 배치하는 필터를 작성합니다.

<li ng-repeat="item in (items|orderBy:'name'|emptyToEnd:'name')">{{item.name}}</li>

코드는 다음과 같습니다.

.filter("emptyToEnd", function () {
    return function (array, key) {
        if(!angular.isArray(array)) return;
        var present = array.filter(function (item) {
            return item[key];
        });
        var empty = array.filter(function (item) {
            return !item[key]
        });
        return present.concat(empty);
    };
});

작업

그나저나, 당신의 바이올린에는 관련된 코드가 없어요.링크를 잘못 사용하셨나요?

업데이트 2: 네가 내 필터를 만지작거려.

여기 아래!d

솔루션은 angularJs의 정상적인 기능을 확장합니다.orderBy필터 - null 값과 정의되지 않은 값의 정규 정렬을 반전할지 여부를 지정하는 세 번째 인수를 사용합니다.전달된 속성 이름(하나뿐 아니라)을 관찰하고 다른 솔루션과 같이 항목에 대해 1초도 반복하지 않습니다.츠키다

<li ng-repeat="item in (items|orderBy:'name':false:true)">{{item.name}}</li>

는 많은 스레드를 했는데, 으로 directly타 i i 에 관한 것이 아니다.orderBy그리고 그들의 기술과 제 자신의 기술을 이렇게 정리했습니다.

angular.module('lib')
.config(['$provide', function ($provide) {
    $provide.decorator('orderByFilter', ['$delegate', '$parse', function ($delegate, $parse) {
        return function () {
            var predicates = arguments[1];
            var invertEmpties = arguments[3];
            if (angular.isDefined(invertEmpties)) {
                if (!angular.isArray(predicates)) {
                    predicates = [predicates];
                }
                var newPredicates = [];
                angular.forEach(predicates, function (predicate) {
                    if (angular.isString(predicate)) {
                        var trimmed = predicate;
                        if (trimmed.charAt(0) == '-') {
                            trimmed = trimmed.slice(1);
                        }
                        var keyFn = $parse(trimmed);
                        newPredicates.push(function (item) {
                            var value = keyFn(item);
                            return (angular.isDefined(value) && value != null) == invertEmpties;
                        })
                    }
                    newPredicates.push(predicate);
                });
                predicates = newPredicates;
            }
            return $delegate(arguments[0], predicates, arguments[2]);
        }
    }])
}]);

이 코드를 말 그대로 사용하려면 앱의 종속성으로 'lib'를 지정해야 합니다.

크레딧 대상:

이 문제에 대한 "즉각적인" 솔루션은 없다고 생각합니다.나는 쉽게 틀릴 수 있다.함수를 술어로 사용한 솔루션을 다음에 제시하겠습니다.

ng-repeat="name in names | orderBy:predicate"

컨트롤러 내부:

$scope.predicate = function(name) {
    return name === '' ? 'zzzzzzz' : !name; 
    /* The 'zzzzzz' forces the empty names to the end, 
      I can't think of a simpler way at the moment. */
}

Klaster_1의 솔루션 외에 필터를 보다 범용적으로 하기 위한 파라미터를 추가합니다.

http://jsfiddle.net/Zukzuk/JZuCX/27/

실행

<tr ng-repeat="name in (names | orderBy:predicate:reverse | orderEmpty:'name':'toBottom')">

필터

.filter('orderEmpty', function () {
    return function (array, key, type) {
        var present, empty, result;

        if(!angular.isArray(array)) return;

        present = array.filter(function (item) {
            return item[key];
        });

        empty = array.filter(function (item) {
            return !item[key]
        });

        switch(type) {
            case 'toBottom':
                result = present.concat(empty);
                break;
            case 'toTop':
                result = empty.concat(present);
                break;

                // ... etc, etc ...

            default:
                result = array;
                break;
        }
        return result;
    };
});

Thnx Klaster_1!

변수 정렬 열을 사용하고 정의되지 않은 값을 음수 값보다 낮게 유지하여 정렬 및 역 정렬

숀의 답변 우아함이 너무 좋아요!사용자에게 정렬할 열과 정렬 방향을 선택할 수 있는 권한을 부여해야 했지만, 음수가 있더라도 정의되지 않은 것은 아래로 떨어지도록 해야 했습니다.

음수를 수정하는 Sean의 주요 통찰력은!!정방향 정렬을 하는 경우에는 '!'+프리케이트를 사용하고 역방향 정렬을 하는 경우에는 '!'+프리케이트를 사용합니다.

다음 토막은 이를 보여줍니다.덧붙여서, 이상한 스코프의 문제가 발생하지 않도록, 술어(정렬하는 속성 선택)와 역행하는 변수를 오브젝트(d) 안에 넣었습니다.사용자 환경에서는 "d"가 필요하지 않을 수 있습니다.

게다가 당신은 아마도 페이지 하단에 있는 나의 형편없는 버튼보다 더 좋은 것을 사용하여 당신의 종류의 술어와 방향을 제어하고 싶을 것이다.그러나, 이것은 코드의 주요 부분을 읽기 쉽게 합니다.

function mainController($scope) {
  $scope.userArray = [
  { name: "Don", age: 20 },
  { name: "Bob", age: 30, height: 170 },
  { name: "Abe", age: 40, height: 160 },
  { name: "Zoe", age: 70 },
  {              age: 70, height: 155 },
  { name: "Shorty",age:45,height: -200},
  { name: "TwinkleInEye", age: -1, height: 152 }
  ]

  $scope.d = {}; // Create an object into which info can be stored and not trashed by Angular's tendency to add scopes
  $scope.d.predicate = "name"; // This string is the name of the property on which to sort
  $scope.d.reverse = false; // True means reverse the sort order
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="" ng-controller="mainController">
  <div ng-repeat="user in (userArray | orderBy: (d.reverse ?['!!'+d.predicate,d.predicate]:['!'+d.predicate,d.predicate]) : d.reverse)">

    Name {{ user.name }} : Age {{ user.age }} : Height {{ user.height }}
  </div>

  <br/>

  <button ng-click="d.predicate='name';">Name</button>
  <button ng-click="d.predicate='age';">Age</button>
  <button ng-click="d.predicate='height';">Height</button> Currently: {{d.predicate}}
 <br/> Leave undefined at bottom, but otherwise: 
  <button ng-click="d.reverse= !d.reverse;">Reverse</button> Currently: {{d.reverse}}

</body>

@Klaster_1은 실제로 어떤 상태에 있었지만, 네스트된 값이 필요하게 되자 필터가 동작하지 않게 되었습니다.또한 역순으로 정렬해도 null 값이 0보다 앞에 표시되도록 했습니다.네스트된 키를 관리하기 위해 $parse를 추가하고 null 값을 언제 상단에 넣어야 하는지 알고 있는 역 파라미터를 추가했습니다.

.filter("emptyToEnd", function ($parse) {
    return function (array, key, reverse) {
        if(!angular.isArray(array)) return;
        var keyFn = $parse(key);
        var present = [];
        var empty = [];

        angular.forEach(array, function(item){
          var val = keyFn(item);
          if(angular.isUndefined(val) || val === null) {
            empty.push(item);
          } else {
            present.push(item);
          }
        });

        if (reverse) {
          return present.concat(empty);
        } else {
          return empty.concat(present);
        }
    };
});

왜 다른 답변에서는 null 값 레코드를 맨 아래에 둘 것을 제안하는지 알 수 없습니다.정상적으로 정렬하는 경우 ASC 순서에서는 모든 null이 맨 위에 있고 DESC 순서에서는 모든 null이 맨 아래에 있음을 의미합니다.여기서 다른 답변을 시도했지만 도움이 되지 않았기 때문에 어레이에서 null을 ""로 변환하는 코드를 변경할 수 있습니다.이렇게 부드럽게 동작합니다.

$scope.convertNullToBlank = function (array) {
  for (var i = 0; i < array.length; i++) {
     if (array[i].col1 === null)
       array[i].col1 = '';

     if (array[i].col2 === null)
        array[i].col2 = '';
  }
  return array;
}

이전 솔루션에 기반한 대체 필터로 지스트를 작성했습니다.https://gist.github.com/360disrupt/1432ee1cd1685a0baf8967dc70ae14b1

필터는 기존 각도 필터를 확장합니다.

angular.module 'tsd.orderByEmptyLast', []
  .filter 'orderByEmptyLast', ($filter) ->
    return (list, predicate, reverse)->
      orderedList = $filter('orderBy')(list, if reverse then ['!' + predicate, '-' + predicate] else ['!' + predicate, predicate] )
      return orderedList

새로운 각도 버전에서는 다음을 포함해야 할 수 있습니다.orderByFilter$filter를 사용하는 대신

angular.module 'tsd.orderByEmptyLast', ['orderByFilter']
  .filter 'orderByEmptyLast', () ->
    return (list, predicate, reverse)->
      orderedList = orderByFilter(list, if reverse then ['!' + predicate, '-' + predicate] else ['!' + predicate, predicate] )
      return orderedList

언급URL : https://stackoverflow.com/questions/18604374/angularjs-orderby-with-empty-field

반응형