4

I have a list that I am loading lazily - only 10 items at a time. When the user scrolls to the bottom another 10 are loaded etc. However I also want to have an option of searching for an item within the full list - not the lazy list. My list exists on client side but is 900+ items and rendering takes long. How can i keep my list displayed lazily but have the search box filter items from my full list.

*I am hoping that creating my on custom search with ng-change() is not my only option

Here is a small plnkr. The letters list is my full list that i want to be searchable. And the cachedLetters is what is rendered in the list

http://plnkr.co/edit/8tyLuo4nSTz1q0Z7DilV?p=preview

HTML

<body ng-app="app" ng-controller="Ctrl">
  <div class="container" style="padding-top:40px">
    <input class="form-control" ng-model="search" style="margin-bottom: 15px">


    <ul class="list-group" style="height: 200px; overflow-y: auto" lazy-load>
      <li class="list-group-item" ng-repeat="letter in cachedLetters | filter: {'name': search}"> {{ letter.name }}</li>
    </ul>
  </div>
</body>

ANGULAR var app = angular.module('app', [])

app.controller('Ctrl', function($scope) {

  $scope.letters = [{
    name: 'A'
  }, {
    name: 'B'
  }, {
    name: 'C'
  }, {
    name: 'D'
  }, {
    name: 'E'
  }, {
    name: 'F'
  }, {
    name: 'G'
  }, {
    name: 'H'
  }, {
    name: 'I'
  }, {
    name: 'J'
  }, {
    name: 'K'
  }, {
    name: 'L'
  }, {
    name: 'M'
  }, {
    name: 'N'
  }, {
    name: 'O'
  }, {
    name: 'P'
  }, {
    name: 'Q'
  }, {
    name: 'R'
  }, {
    name: 'S'
  }, {
    name: 'T'
  }, {
    name: 'U'
  }, {
    name: 'V'
  }, {
    name: 'W'
  }, {
    name: 'X'
  }, {
    name: 'Y'
  }, {
    name: 'Z'
  }, ]

  var ind = 0

  $scope.cachedLetters = $scope.letters.slice(0, 10)

  $scope.loadMore = function() {
    ind = ind + 10
    var r = 10
    if (ind + 10 > $scope.letters.length) {
      r = $scope.letters.length - ind
    }
    console.log("Loading")
    $scope.cachedLetters = $scope.cachedLetters.concat($scope.letters.slice(ind, r + ind))
    }

  })

app.directive('lazyLoad', function() {
  return {
    restrict: 'A',
    link: function(scope, elem) {
      var scroller = elem[0]
      $(scroller).bind('scroll', function() {
        if (scroller.scrollTop + scroller.offsetHeight >= scroller.scrollHeight) {
          scope.$apply('loadMore()')
        }
      })
    }
  }
})
Dale
  • 352
  • 2
  • 15

1 Answers1

7

Here is a solution i have come up with. not sure if there is a better solution.

http://plnkr.co/edit/seshxi?p=preview

see plnkr for solution
Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
Dale
  • 352
  • 2
  • 15
  • do you think there is anyway to achieve this without using $scope? I am using the new angular router which won't let me use $scope and really want to achieve this! – Jess Anastasio Apr 05 '16 at 00:38
  • You could perhaps pass the function pointer to the directive. Then instead of using scope.$apply you could just call the function passed in – Dale Apr 11 '16 at 08:37