frikkievb frikkievb - 2 months ago 23
AngularJS Question

AngularJS: Angular Material Virtual Repeat & md-list

I am experiencing strange behavior when using the virtual repeat along with the md-list. Here is my issue as outlined on GitHub:

Actual Behavior:

What is the issue? *

Not all items are being rendered on md-list when list is implemented as md-virtual-repeat-container.

What is the expected behavior?

I expected that all items be rendered.

CodePen Demo which shows your issue:

http://codepen.io/frikkievb/pen/VKbEXZ

Details: I found that certain values are not being rendered on the md-list. On my side it is usually items starting on the 0 index of each page.

Angular Versions:

Angular Version: 1.5.5

Angular Material Version: v1.1.1

Browser Type: * Chrome

Browser Version: * 53.0.2785.116 m

OS: * Windows 10

HTML

<div ng-controller="MyAppController as ctrl" ng-cloak="" class="virtualRepeatdemoDeferredLoading" ng-app="MyApp">

<md-content layout="column">
<div ui-view="projectContent">

<md-list md-virtual-repeat-container style="height:500px">
<md-list-item class="md-2-line" md-virtual-repeat="item in ctrl.items" md-on-demand ng-click="ctrl.edit()">
Item: {{item}}
</md-list-item>
</md-list>
</div>


</div>


JavaScript

/**
* Created by frikk on 2016/08/01.
*/

(function () {

function MyAppController() {

var vm = this;
vm.edit = edit;

vm.items = {

pages: [],
pageSize: 10,
getItemAtIndex: function (index) {

var pageNumber = Math.floor(index / this.pageSize);
var page = this.pages[pageNumber];
if (page) {
return page[index % this.pageSize];
} else if (page !== null) {
this.fetchPage(pageNumber);
}
},
getLength: function () {
return 50;
},
fetchPage: function (pageNumber) {
this.pages[pageNumber] = null;
var pageOffset = pageNumber * this.pageSize;
this.pages[pageNumber] = [];
for (var i = pageOffset; i < pageOffset + this.pageSize; i++) {
this.pages[pageNumber].push(i);
}
}
}



function edit() {

}
}

angular.module("MyApp",[
"ngAria",
"ngAnimate",
"ngMessages",
"ngMaterial",
])
.controller("MyAppController", [MyAppController]);
})()

Answer

It's a very unusual problem that I've partially fixed - CodePen

Following on from the examples in the demos I introduced a $timeout in fetchPage. This solves the problem of not displaying all the items. However, you will notice a slight delay displaying some items initially.

JS

(function () {
    MyAppController.$inject = ["$timeout"];

    function MyAppController($timeout) {
      var vm = this;

      vm.items = {

        pages: [],
        pageSize: 10,
        temp: [],
        getItemAtIndex: function (index) {

          var pageNumber = Math.floor(index / this.pageSize);
          var page = this.pages[pageNumber];
          if (page) {
            return page[index % this.pageSize];
          } else if (page !== null) {
            this.fetchPage(pageNumber);
          }
        },
        getLength: function () {
          return 50;
        },
        fetchPage: function (pageNumber) {
          var pageOffset = pageNumber * this.pageSize;
          this.pages[pageNumber] = [];
          this.temp = [];
          for (var i = pageOffset; i < pageOffset + this.pageSize; i++) {
            this.temp.push(i);
          }
          $timeout(angular.noop).then(angular.bind(this, function () {
            this.pages[pageNumber] = this.temp;
          }));
        }
      }
    }

    angular.module("MyApp",[
      "ngAria",
      "ngAnimate",
      "ngMessages",
      "ngMaterial",
    ])
      .controller("MyAppController", MyAppController);
})()
Comments