So I had a grid of images I displayed with an Angular ng-repeat, where the number of images was in the hundreds. This was just killing performance and overloading the DOM. I was getting super frustrated with the choppy scrolling and overall slow loading.
It occurred to me to use a virtual repeater, however, they either support vertical or horizontally stacked elements, not a grid. In order to get this to work, I need to structure my elements in a 2D array. That way I could still use the repeater on spitting out rows of image arrays and gain a performance boost through that.
2D Structure:
[
[img, img, img, img] ,
[img, img, img, img] ,
[img, img, img, img] ,
[img, img, img, img]
]
img = the image source url
The first thing I did, was make sure I knew the width of the total space for the grid and width of each element. I want to make sure I fill the space, so I did the math to know how many elements will fill the total space and that will be my column count. I recommend to setup some listeners on the grid width to catch changes from the user changing the window size, I won’t be showing that part in this example. The snippet below shows the creation of my 2D array that will be fed to the repeater.
//Passing in my array of images that I need to break down into a 2D array
//Also, including the width of the entire grid space and each image's uniformed width
function computeRows(imageArray, width, imageWidth) {
var rows = [];
if (imageArray) {
const rowCount = width/ imageWidth;
const copy = imageArray.slice(); //using a copy instead of affecting actual element
while (copy.length) { //create the 2D array by looping through the imageArray and splicing it into chunks
rows.push(copy.splice(0, rowCount));
}
}
return rows;
}
//Will need to bind computeRows() to the scope
Once I have my 2D array, I bound it to me scope and used it in my template. I chose to use vs-repeat because it was very quick and easy to implement.
<div vs-repeat vs-excess="10">
<div ng-repeat="row in rows">
<img
ng-repeat="img in row"
ng-src="{{img}}"/>
</div>
</div>
That was it, the end result was awesome, vs-repeat handled just showing what was necessary for the user experience and loading the remainder DOM elements as the user scrolled through the grid.