Угловой фильтр и лимит не работают как положено

Я новичок в angular.js и вижу то, что мне не нравится. Когда я фильтрую и ограничиваю данные одновременно, создается впечатление, что ограничение влияет на фильтр и не может выполнить поиск в исходном массиве. Я что-то пропустил?

ОБНОВЛЕНИЕ: Дело в том, что я пытаюсь создать простую директиву таблицы данных с нумерацией страниц, фильтром и некоторыми другими вещами, но это сводит меня с ума. Я видел ответы и комментарии, и мне интересно, если процедура, которую я пытаюсь достичь, является неправильной, но нет, логически ограничение не должно влиять на фильтр (я так думаю), потому что, возможно, через некоторое время вы ' Вам нужно будет искать во всем источнике, а не в ограниченной части, они должны быть разделены по поведению. Разве это не поведение по умолчанию, которое я видел в основных структурах datatables?

Вот пример, описывающий проблему:

angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) {
        $scope.q="john"
        $scope.friends = [
          {name:'John', age:25, gender:'boy'},
          {name:'Jessie', age:30, gender:'girl'},
          {name:'Johanna', age:28, gender:'girl'},
          {name:'Joy', age:15, gender:'girl'},
          {name:'Mary', age:28, gender:'girl'},
          {name:'Peter', age:95, gender:'boy'},
          {name:'Sebastian', age:50, gender:'boy'},
          {name:'Erika', age:27, gender:'girl'},
          {name:'Patrick', age:40, gender:'boy'},
          {name:'Samantha', age:60, gender:'girl'}
        ];
      });
.example-animate-container {
        background:white;
        border:1px solid black;
        list-style:none;
        margin:0;
        padding:0 10px;
      }

      .animate-repeat {
        line-height:30px;
        list-style:none;
        box-sizing:border-box;
      }

      .animate-repeat.ng-move,
      .animate-repeat.ng-enter,
      .animate-repeat.ng-leave {
        transition:all linear 0.5s;
      }

      .animate-repeat.ng-leave.ng-leave-active,
      .animate-repeat.ng-move,
      .animate-repeat.ng-enter {
        opacity:0;
        max-height:0;
      }

      .animate-repeat.ng-leave,
      .animate-repeat.ng-move.ng-move-active,
      .animate-repeat.ng-enter.ng-enter-active {
        opacity:1;
        max-height:30px;
      }
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-animate.min.js"></script>
<div ng-app="ngRepeat" ng-controller="repeatController">
The flollowing example shows when you filter and limit the data at the same time, you can not filter the items before the current position.
<br/>
<b>position</b> : 5<br/>
<b>limitTo</b> : 5<br/>
<b>filter</b> : { '$' : '{{q}}' }<br/>
        I have {{friends.length}} friends. They are:
        <input type="search" value="john" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
        <ul class="example-animate-container">
          <li class="animate-repeat" ng-repeat="friend in friends | filter:q | limitTo : 5 : 5 as result track by $index">
            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
          </li>
          <li class="animate-repeat" ng-if="results.length == 0">
            <strong>No results found...</strong>
          </li>
        </ul>
<br/>As you can see there's no results.
      </div>

4 ответа

Решение

Следуя философии DataTables.net, когда вы запускаете фильтр данных, он возвращается на первую страницу. Я надеюсь, что это помогает другим

angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) {
        $scope.position=5;
        $scope.resetPagination = function(){
          if(this.position !== 0) this.position = 0;
        }
        $scope.friends = [
          {name:'John', age:25, gender:'boy'},
          {name:'Jessie', age:30, gender:'girl'},
          {name:'Johanna', age:28, gender:'girl'},
          {name:'Joy', age:15, gender:'girl'},
          {name:'Mary', age:28, gender:'girl'},
          {name:'Peter', age:95, gender:'boy'},
          {name:'Sebastian', age:50, gender:'boy'},
          {name:'Erika', age:27, gender:'girl'},
          {name:'Patrick', age:40, gender:'boy'},
          {name:'Samantha', age:60, gender:'girl'}
        ];
      });
.example-animate-container {
        background:white;
        border:1px solid black;
        list-style:none;
        margin:0;
        padding:0 10px;
      }

      .animate-repeat {
        line-height:30px;
        list-style:none;
        box-sizing:border-box;
      }

      .animate-repeat.ng-move,
      .animate-repeat.ng-enter,
      .animate-repeat.ng-leave {
        transition:all linear 0.5s;
      }

      .animate-repeat.ng-leave.ng-leave-active,
      .animate-repeat.ng-move,
      .animate-repeat.ng-enter {
        opacity:0;
        max-height:0;
      }

      .animate-repeat.ng-leave,
      .animate-repeat.ng-move.ng-move-active,
      .animate-repeat.ng-enter.ng-enter-active {
        opacity:1;
        max-height:30px;
      }
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-animate.min.js"></script>
<div ng-app="ngRepeat" ng-controller="repeatController">
The flollowing example shows when you filter and limit the data at the same time, you can not filter the items before the current position.
<br/>
<b>limitTo</b> : 5<br/>
<b>position</b> : {{position}}<br/>
<b>filter</b> : { '$' : '{{q}}' }<br/>
        I have {{friends.length}} friends. They are:
        <input type="search" value="john" ng-model="q" placeholder="filter friends..." aria-label="filter friends" ng-change="resetPagination()"/>
        <ul class="example-animate-container">
          <li class="animate-repeat" ng-repeat="friend in friends | filter:q | limitTo : 5 : position as results track by $index">
            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
          </li>
          <li class="animate-repeat" ng-if="results.length == 0">
            <strong>No results found...</strong>
          </li>
        </ul>
<br/>As you can see there's results.
      </div>

У вас есть проблемы, потому что ваш limitTo ограничивает 5 элементов, начиная с индекса 5, при поиске, скорее всего, не будет 5 элементов, особенно с учетом предоставленных данных.

+ Изменить

limitTo : 5 : 5 track by $index

в

limitTo : 5 track by $index

или же

limitTo : 5 : 0 track by $index // 0 = Index at which to begin limitation

Я нашел результат, используя это

ng-repeat="friend in friends | filter:q | limitTo : 5 as results track by $index"

Это может помочь вам.. это с нумерацией страниц

<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-animate.min.js"></script>
<script>
    var app=angular.module('ngRepeat', ['ngAnimate']);
    app.controller('repeatController', function($scope) {
    $scope.q="john";
    $scope.currentPage = 0;
    $scope.pageSize = 5;
    $scope.numberOfPages=function(){
        return Math.ceil($scope.friends.length/$scope.pageSize);                
    }
    $scope.friends = [
      {name:'John', age:25, gender:'boy'},
      {name:'Jessie', age:30, gender:'girl'},
      {name:'Johanna', age:28, gender:'girl'},
      {name:'Joy', age:15, gender:'girl'},
      {name:'Mary', age:28, gender:'girl'},
      {name:'Peter', age:95, gender:'boy'},
      {name:'Sebastian', age:50, gender:'boy'},
      {name:'Erika', age:27, gender:'girl'},
      {name:'Patrick', age:40, gender:'boy'},
      {name:'Samantha', age:60, gender:'girl'}
    ];
  });
  app.filter('startFrom', function() {
    return function(input, start) {
        start = +start; //parse to int
        return input.slice(start);
    }
});
</script>


<style>
    .example-animate-container {
        background: white;
        border: 1px solid black;
        list-style: none;
        margin: 0;
        padding: 0 10px;
    }

    .animate-repeat {
        line-height: 30px;
        list-style: none;
        box-sizing: border-box;
    }

    .animate-repeat.ng-move,
    .animate-repeat.ng-enter,
    .animate-repeat.ng-leave {
        transition: all linear 0.5s;
    }

    .animate-repeat.ng-leave.ng-leave-active,
    .animate-repeat.ng-move,
    .animate-repeat.ng-enter {
        opacity: 0;
        max-height: 0;
    }

    .animate-repeat.ng-leave,
    .animate-repeat.ng-move.ng-move-active,
    .animate-repeat.ng-enter.ng-enter-active {
        opacity: 1;
        max-height: 30px;
    }
</style>

<div ng-app="ngRepeat" ng-controller="repeatController">
    The flollowing example shows when you filter and limit the data at the same time, you can not filter the items before the
    current position.
    <br/>
    <b>position</b> : 5<br/>
    <b>limitTo</b> : 5<br/>
    <b>filter</b> : { '$' : '{{q}}' }<br/> I have {{friends.length}} friends. They are:
    <input type="search" value="john" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
    <ul class="example-animate-container">
        <li class="animate-repeat" ng-repeat="friend in friends | filter:q | startFrom:currentPage*pageSize | limitTo:pageSize as results track by $index">
            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
        </li>
        <li class="animate-repeat" ng-if="results.length == 0">
            <strong>No results found...</strong>
        </li>
    </ul>
    <button ng-disabled="currentPage == 0" ng-click="currentPage=currentPage-1">
    Previous
</button>
{{currentPage+1}}/{{numberOfPages()}}
<button ng-disabled="currentPage >= friends.length/pageSize-1" ng-click="currentPage=currentPage+1;">
    Next
</button>
</div>

Другие вопросы по тегам