2015-11-17 3 views
6

Я использую директиву Angular Material, чтобы иметь бесконечный прокрутки, и мне нужно заменить его на функцию timeout demo $ с запросом $ http. Но я не могу найти правильное решение. В приведенном ниже коде бесконечная прокрутка работает нормально, но не отображает данные из запроса http. Проблема в том, что я не знаю способ привязки результата $ http к infinItems.

Here является плункер.

Index.html

<body ng-app="infiniteScrolling" class="virtualRepeatdemoInfiniteScroll"> 
<div ng-controller="AppCtrl as ctrl" ng-cloak> 
    <md-content layout="column"> 
     <md-virtual-repeat-container id="vertical-container" flex> 
      <div md-virtual-repeat="item in ctrl.infiniteItems" md-on-demand 
       class="repeated-item" flex> 
       {{item.id}} 
      </div> 
     </md-virtual-repeat-container> 
    </md-content> 
</div> 
</body> 

JS:

(function() { 
'use strict'; 
angular 
    .module('infiniteScrolling', ['ngMaterial']) 
    .controller('AppCtrl', function ($timeout,$scope,$http) { 
    this.infiniteItems = { 
      numLoaded_: 0, 
      toLoad_: 0, 
      items:[], 
      getItemAtIndex: function (index) { 
       if (index > this.numLoaded_) { 
        this.fetchMoreItems_(index); 
        return null; 
       } 
       return index; 
      }, 
      getLength: function() { 
       return this.numLoaded_ + 5; 
      }, 
      fetchMoreItems_: function (index) { 
       if (this.toLoad_ < index) { 
        this.toLoad_ += 20; 

        $http.get('items.json').success(function (data) { 
         var items = data; 
         for (var i = 0; i < items.length; i++) { 
          this.items.push(items[i].data); 
         } 
         this.numLoaded_ = this.toLoad_; 
        }.bind(this)); 
       } 
      } 
     }; 
    }); 
})(); 

ответ

11

Это один работает:

plnkr

  • getItemAtIndex вернулся индекс, а не пункт
  • если вы осмотрели то, что вы толкали, вы бы увидели, что в строке 33 в моем plunkr я Concat obj.data, а не простой obj
(function() { 
    'use strict'; 
    angular.module('infiniteScrolling', ['ngMaterial']) 
     .controller('AppCtrl', function ($scope, $http) { 
      // In this example, we set up our model using a plain object. 
      // Using a class works too. All that matters is that we implement 
      // getItemAtIndex and getLength. 
      var vm = this; 
      vm.infiniteItems = { 
       numLoaded_: 0, 
       toLoad_: 0, 
       items: [], 

       // Required. 
       getItemAtIndex: function (index) { 
        if (index > this.numLoaded_) { 
         this.fetchMoreItems_(index); 
         return null; 
        } 
        return this.items[index]; 
       }, 

       // Required. 
       getLength: function() { 
        return this.numLoaded_ + 5; 
       }, 

       fetchMoreItems_: function (index) { 
        if (this.toLoad_ < index) { 
         this.toLoad_ += 5; 
         $http.get('items.json').then(angular.bind(this, function (obj) { 
          this.items = this.items.concat(obj.data); 
          this.numLoaded_ = this.toLoad_; 
         })); 
        } 
       } 
      } 
     }) 
})(); 
+0

Спасибо, он работает. Но я не знаю, почему для toLoad _ + = 20, когда я спускаюсь по прокрутке, данные загружаются с большой задержкой, очень никогда не загружаются не то же самое для toLoad _ + = 10. –

+0

Ну, на самом деле он создает элемент в DOM, но так как ваш api возвращает 5 элементов, iirc, у него недостаточно данных для инициализации, поэтому они пусты/пусты. –

+1

Спасибо, ты прав. Я просто хочу добавить еще один момент: я думаю, что замена 'data' на' obj.data' не является частью решения, поскольку я использовал 'success' вместо' then' и возвращает данные не результат, но используя 'concat 'является частью решения. Потому что когда я удаляю код, он работает неправильно. Он имеет недостаток, поскольку он хранит все данные (все данные вне поля зрения) в памяти не только с учетом данных. –

0

На каждый вызов api пытается получить, потому что у db есть еще несколько записей или нет. и добавьте это условие в функцию fetchMoreItems_.

fetchMoreItems_: function (index) { 
       if (this.toLoad_ < index && hasMoreRecords) { 
        this.toLoad_ += 5; 

В нашем коде мы получаем детали как

  • sCurrentPage: 3
  • Smore: правда == >> это указывает на то, что дб имеет больше записей или нет после того, как выборка страниц мудрыми данных ,
  • sTotalPages: 4
  • sTotalRecords: 36
+0

И вы говорите, что он создает элемент в DOM, и если мы получаем меньше записей, которые показывают пустые записи. Итак, как я могу удалить или прекратить генерировать эти пустые записи. Не могли бы вы помочь ... –

0

пришел сюда и увидел @ Alessandro-Buggin ответ, который был очень полезным. Мне пришлось немного изменить его, поэтому я решил поделиться им, чтобы другие могли помочь. Мне нужно было:

  • , чтобы избежать получения запросов прокрутки в то время как уже восстановление данных (с использованием this.hold)
  • остановки запросов, когда все данные, полученные от внутреннего интерфейса (с использованием this.stop_)
  • скрывается содержание во время загрузки, чтобы избегайте глюков или пустых элементов (опять же используя this.hold). В представлении вам нужно использовать ng-hide на этом элементе, потому что ng-if избегает существования элемента, поэтому он не будет загружаться в первый раз.
  • реализация метода обновления для перезагрузки данных при изменении параметров/фильтров из внешней формы.

Далеко от совершенства, но работает очень хорошо.

vm.elements = null; 
vm.infiniteItems = { // Start of infinte logic 

stop_: false, 
hold: false, 
numLoaded_: 0, 
toLoad_: 0, 
items: [], 

refresh: function() { 
    this.stop_ = false; 
    this.hold = false; 
    this.numLoaded_ = 0; 
    this.toLoad_ = 0; 
    this.items = []; 
}, 

getItemAtIndex: function (index) { 
    if (!this.hold) { 
     if (index > this.numLoaded_) { 
      this.fetchMoreItems_(index); 
      return null; 
     } 
    } 
    return this.items[index]; 
}, 

getLength: function() { 
    if (this.stop_) { 
     return this.items.length; 
    } 
    return this.numLoaded_ + 5; 
}, 

fetchMoreItems_: function (index) { 
    if (this.toLoad_ < index) { 

     this.hold = true; 
     this.toLoad_ += 5; 

     var start = this.numLoaded_; 
     if (start > 0) start++; 

     MyService.getData(parameters) 
     .then(angular.bind(this, function (obj) { 

      if (obj && obj.elements > 0) { 
      vm.elements = obj.elements; 
      this.items = this.items.concat(obj.data); 

      if (obj.elements < this.toLoad_) { 
       this.stop_ = true; 
      } 
      this.numLoaded_ = this.items.length; 
      this.hold = false; 

      } else { // if no data 
      vm.elements = 0; 
      } 
     })); 
    } 
} 

} // End of infinte logic 

Примечание: моя служба возвращает объект, состоящий, как это: obj = {elements: INTEGER, data: ARRAY} где элементы говорит вам длину полного запроса.

Смежные вопросы