Created
May 5, 2016 00:06
-
-
Save scyrizales/f2a297db522e2d789f69f70e7151ce7e to your computer and use it in GitHub Desktop.
SimpleVirtualRepeater - This is an simple solution to handle thousands of results on an ng-repeat without sacrificing performance.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
'use strict'; | |
angular.module('simple-virtual-repeater', []) | |
.directive('virtualRepeater', virtualRepeater); | |
virtualRepeater.$inject = ['$compile', '$timeout']; | |
function virtualRepeater($compile, $timeout) { | |
var directive = { | |
restrict: 'EA', | |
replace: 'true', | |
transclude: true, | |
template: '<div class="virtual-repeat"><div class="virtual-repeat-before"></div><div ng-transclude=""></div><div class="virtual-repeat-after"></div></div>', | |
link: function postLink(scope, iElement, iAttrs, controller) { | |
var internalRepeat = iElement.find("[ng-transclude]"), | |
beforeRepeat = iElement.find(".virtual-repeat-before"), | |
afterRepeat = iElement.find(".virtual-repeat-after"), | |
parent = iElement.parent(); | |
internalRepeat.hide(); | |
var expressionMatches = /^\s*(\S+)\s+in\s+([\S\s]+?)(track\s+by\s+\S+)?$/.exec(iAttrs.virtualRepeat), | |
lhs = expressionMatches[1], | |
rhs = expressionMatches[2], | |
rhsSuffix = expressionMatches[3] || ''; | |
var itemsAllowed = +(iAttrs.itemsAllowed || 5), totalItems = [], itemHeight = 0; | |
var repeater = angular.element('<div class="virtual-repeat-item" ng-repeat="' + lhs + ' in virtualRepeatCollection ' + rhsSuffix + '"></div>'); | |
repeater.html(internalRepeat.html()); | |
scope.virtualRepeatCollection = []; | |
scope.$watchCollection(rhs, function (data) { | |
if (data) { | |
totalItems = data; | |
scope.virtualRepeatCollection = totalItems.slice(0, itemsAllowed); | |
$timeout(function () { | |
itemHeight = iElement.find(".virtual-repeat-item:first").height(); | |
parent.scrollTop(0); | |
beforeRepeat.css("height", 0); | |
afterRepeat.css("height", itemHeight * (totalItems.length - itemsAllowed)); | |
}); | |
} | |
}); | |
internalRepeat.after($compile(repeater)(scope)); | |
parent.on('scroll', function () { | |
var movedDistance = parent.scrollTop(), | |
movedItems = Math.floor(movedDistance / itemHeight); | |
movedItems = (movedItems > 0)? movedItems - 1 : 0; | |
scope.virtualRepeatCollection = totalItems.slice(movedItems, movedItems + itemsAllowed); | |
beforeRepeat.css("height", itemHeight * (movedItems)); | |
afterRepeat.css("height", itemHeight * (totalItems.length - movedItems - itemsAllowed)); | |
scope.$apply(); | |
}); | |
} | |
}; | |
return directive; | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you want to use you should do this:
replace your
with
items-allowed is the ammount of items you gonna display... Play with it until you find how many items you need to fill the container div.
I hope you like it :)