1

I'm a newbie in angular.js and I'm seeing something I don't like. When I filter and limit the data at the same time, seems like the limit affects the filter and it can't search back in the original array source. Am I missing something?

UPDATE: Thing is I'm trying to create a simple data table directive with pagination, filter and some other things, but this is driving me crazy. I've seen the answers and comments and I'm wondering if the procedure that I'm trying to reach is wrong, but no, logically the limit must no affect the filter (I think so), because maybe in some time you'll need to search back in the whole source, not the limmitted part, they should be separated behaviors. Isn't this the default behavior I've seen in major datatables frameworks?

Here is an example describing the issue:

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>

3
  • Remove the second parameter of limitTo filter and it should work. Commented Aug 4, 2016 at 12:45
  • Please read the update part Commented Aug 4, 2016 at 13:12
  • "logically the limit must no affect the filter". No, of course it should affect. Commented Aug 4, 2016 at 13:14

4 Answers 4

1

You are having issues because your limitTo is limiting 5 items, beginning from index 5, when you search there will most likely not be 5 items, especially not with the data provided.

Change

limitTo : 5 : 5 track by $index

to

limitTo : 5 track by $index

or

limitTo : 5 : 0 track by $index // 0 = Index at which to begin limitation
Sign up to request clarification or add additional context in comments.

6 Comments

"Your limitTo is wrong". Well, It isn't wrong, it just doesn't work as he expecting.. but it's a valid use of limitTo.
@PedroMora, 'logically the limit must not affect the filter' this is the case, the issue you are having is that you are limiting to 5 from index 5. This means, if you search for 'girl' you get six results, but you are limiting to five from index 5, hence it is only showing one result
Then, do I have to create my own decorator???, man, I was comfortable with angular till I got this part. This is the default behavior I've seen in major datatables frameworks
no, use limitTo : 5 track by $index or limitTo : 5 : 0 track by $index, this will filter your list, and limit the results from index 0 - 5
@PedroMora, since you're just starting is always good to read the docs. docs.angularjs.org/api/ng/filter/limitTo
|
0

I have found result using this

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

1 Comment

Please, set yourself in context of paging behavior of datatable, no matter the page you are, if you filter the datatable it returns matched items.
0

Following DataTables.net philosophy, when you start filter data, it goes back to the first page. I hope it helps others

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>

Comments

0

This may help you..this is with pagination

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

1 Comment

Still don't work, if you remove $scope.q = "john" from controller and then filter data, the issue is same as mine.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.