{"id":1234,"date":"2018-02-24T09:56:43","date_gmt":"2018-02-24T16:56:43","guid":{"rendered":"http:\/\/somethingk.com\/main\/?p=1234"},"modified":"2018-02-24T09:58:05","modified_gmt":"2018-02-24T16:58:05","slug":"angularjs-virtual-repeater-with-a-grid","status":"publish","type":"post","link":"https:\/\/somethingk.com\/main\/angularjs-virtual-repeater-with-a-grid\/","title":{"rendered":"AngularJs Virtual Repeater with a Grid"},"content":{"rendered":"<section id=\"text-4\" class=\"widget boka-widget widget_text amr_widget\">\t\t\t<div class=\"textwidget\"><script async src=\"\/\/pagead2.googlesyndication.com\/pagead\/js\/adsbygoogle.js\"><\/script>\r\n<ins class=\"adsbygoogle\"\r\n     style=\"display:block; text-align:center;\"\r\n     data-ad-layout=\"in-article\"\r\n     data-ad-format=\"fluid\"\r\n     data-ad-client=\"ca-pub-7619916617995509\"\r\n     data-ad-slot=\"9102150708\"><\/ins>\r\n<script>\r\n     (adsbygoogle = window.adsbygoogle || []).push({});\r\n<\/script><\/div>\n\t\t<\/section>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>2D Structure:<br \/>\n[<br \/>\n[img, img, img, img] ,<br \/>\n[img, img, img, img] ,<br \/>\n[img, img, img, img] ,<br \/>\n[img, img, img, img]<br \/>\n]<\/p>\n<p>img = the image source url<\/p>\n<p>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&#8217;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.<\/p>\n<div class=\"snippetcpt-wrap\" id=\"snippet-1236\" data-id=\"1236\" data-edit=\"\" data-copy=\"\/main\/wp-json\/wp\/v2\/posts\/1234?snippet=17b1fac833&#038;id=1236\" data-fullscreen=\"https:\/\/somethingk.com\/main\/code-snippets\/creating-the-2d-array\/?full-screen=1\">\n\t\t\t\t<pre class=\"prettyprint linenums lang-javascript\" title=\"Creating the 2D Array\">\/\/Passing in my array of images that I need to break down into a 2D array\r\n\/\/Also, including the width of the entire grid space and each image's uniformed width\r\nfunction computeRows(imageArray, width, imageWidth) {\r\n    var rows = [];\r\n    if (imageArray) {\r\n        const rowCount = width\/ imageWidth;\r\n        const copy = imageArray.slice(); \/\/using a copy instead of affecting actual element\r\n        while (copy.length) { \/\/create the 2D array by looping through the imageArray and splicing it into chunks\r\n            rows.push(copy.splice(0, rowCount)); \r\n        }\r\n    }\r\n    return rows;\r\n}\r\n\/\/Will need to bind computeRows() to the scope<\/pre>\n\t\t\t<\/div>\n<p>Once I have my 2D array, I bound it to me <strong>scope<\/strong> and used it in my template. I chose to use <a href=\"https:\/\/github.com\/kamilkp\/angular-vs-repeat\">vs-repeat<\/a> because it was very quick and easy to implement.<\/p>\n<div class=\"snippetcpt-wrap\" id=\"snippet-1237\" data-id=\"1237\" data-edit=\"\" data-copy=\"\/main\/wp-json\/wp\/v2\/posts\/1234?snippet=17b1fac833&#038;id=1237\" data-fullscreen=\"https:\/\/somethingk.com\/main\/code-snippets\/template-2d-repeater-example\/?full-screen=1\">\n\t\t\t\t<pre class=\"prettyprint linenums lang-html\" title=\"Template 2D Repeater Example\">&lt;div vs-repeat vs-excess=&quot;10&quot;&gt;\r\n    &lt;div ng-repeat=&quot;row in rows&quot;&gt;\r\n        &lt;img \r\n            ng-repeat=&quot;img in row&quot;\r\n            ng-src=&quot;{{img}}&quot;\/&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/div&gt;<\/pre>\n\t\t\t<\/div>\n<p>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.<\/p>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter size-full wp-image-1238\" src=\"http:\/\/somethingk.com\/main\/wp-content\/uploads\/2018\/02\/Screen-Shot-2018-02-24-at-9.11.10-AM.png\" alt=\"\" width=\"1670\" height=\"906\" srcset=\"https:\/\/somethingk.com\/main\/wp-content\/uploads\/2018\/02\/Screen-Shot-2018-02-24-at-9.11.10-AM.png 1670w, https:\/\/somethingk.com\/main\/wp-content\/uploads\/2018\/02\/Screen-Shot-2018-02-24-at-9.11.10-AM-300x163.png 300w, https:\/\/somethingk.com\/main\/wp-content\/uploads\/2018\/02\/Screen-Shot-2018-02-24-at-9.11.10-AM-768x417.png 768w, https:\/\/somethingk.com\/main\/wp-content\/uploads\/2018\/02\/Screen-Shot-2018-02-24-at-9.11.10-AM-1024x556.png 1024w, https:\/\/somethingk.com\/main\/wp-content\/uploads\/2018\/02\/Screen-Shot-2018-02-24-at-9.11.10-AM-350x190.png 350w\" sizes=\"(max-width: 1670px) 100vw, 1670px\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[177],"tags":[657,639,620,655,323,658,593,653,654,656],"class_list":["post-1234","post","type-post","status-publish","format-standard","hentry","category-development","tag-2d-array","tag-angularjs","tag-dom","tag-grid","tag-javascript","tag-optimization","tag-performance","tag-repeater","tag-virtual-repeater","tag-vs-repeat"],"_links":{"self":[{"href":"https:\/\/somethingk.com\/main\/wp-json\/wp\/v2\/posts\/1234","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/somethingk.com\/main\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/somethingk.com\/main\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/somethingk.com\/main\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/somethingk.com\/main\/wp-json\/wp\/v2\/comments?post=1234"}],"version-history":[{"count":3,"href":"https:\/\/somethingk.com\/main\/wp-json\/wp\/v2\/posts\/1234\/revisions"}],"predecessor-version":[{"id":1240,"href":"https:\/\/somethingk.com\/main\/wp-json\/wp\/v2\/posts\/1234\/revisions\/1240"}],"wp:attachment":[{"href":"https:\/\/somethingk.com\/main\/wp-json\/wp\/v2\/media?parent=1234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/somethingk.com\/main\/wp-json\/wp\/v2\/categories?post=1234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/somethingk.com\/main\/wp-json\/wp\/v2\/tags?post=1234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}