AngularJS deferred rendering (not deferred loading views)

Imagine having over 3000 items to display within a fixed-height div using an ng-repeat and setting overflow: auto. This would result in only a portion of the items being visible with the rest accessible via scrollbar.

It's anticipated that simply running an ng-repeat on such a large number of items may lead to performance issues. Is there a method available in AngularJS to render only the currently visible items?

Edit:

An infinite scroll option is not desired in this scenario. The objective is to allow users to freely navigate through the list similar to how one navigates a text editor. To clarify, the scrollbar should encompass the entire height of all items, while maintaining a minimal presence of items in the DOM at any given time.

Answer №1

This solution proposes a method for lazy-rendering only the items currently in view based on the edited version of the original question. The goal is to allow users to scroll through the list freely, similar to the behavior of a text editor. In other words, the scroll should cover the "height" of all items, but only display a few in the DOM at a time.

Before implementing this, make sure to install the angular-inview plugin.

To calculate the scroll height, you need something to reserve space for your array items. Start by creating an array with 3000 simple items (or integrate with infinite scroll as needed).

var $app = angular.module('app', ['infinite-scroll']);

$app.controller('listingController', function($scope, $window) {
  $scope.listOfItems = new Array($window._bootstrappedData.length);
  $scope.loadItem = function($index,$inview) {
    if($inview) {
      $scope.listOfItems[$index] = $window._bootstrappedData[$index];
    }
  }
});

Considering variable item heights, it's advisable to create a placeholder representing the pre-rendered content.

<div ng-controller="listingController">
  <ul>
    <li ng-repeat="item in listOfItems track by $index" in-view="loadItem($index,$inview)" style="min-height:100px"><div ng-if="item">{{item.name}}</div></li>
  </ul>
</div>

Utilizing ng-if helps optimize rendering efficiency. When an item comes into view while scrolling, it will be automatically displayed. To introduce a delay before showing the item, consider adding a timeout within the loadItem function that cancels if the same index goes out of view quickly.

Note: To entirely avoid adding elements to the DOM, set your scrollable area to a multiple of the "placeholder" height. Then develop a directive that uses this height to determine which items should be displayed. As new items appear, include their heights and position them correctly, adjusting the displayed elements accordingly. However, this approach might be too extreme and unnecessary.

Answer №2

Expanding on Grundy's idea of utilizing the .slice() method.

Whenever I need to implement lazy-rendering or lazy-loading of data, I rely on ngInfiniteScroll.

To prevent overloading digest performance unnecessarily, it is advisable to keep a large number of records, like 3000 in this case, out of your scope and only append them as required. Here’s how you can achieve this:

var $app = angular.module('app', ['infinite-scroll']);

$app.controller('listingController', function($scope, $window) {

  // Bootstrap your data outside this controller to a non-digested array
  var currentPage, pageLength;
  $scope.listOfItems = [];
  currentPage = 0;
  pageLength = 100;
  $scope.nextPage = function() {
    if (currentPage * pageLength >= $window._bootstrappedData.length) {
      return false;
    }
    
    $scope.listOfItems.push($window._bootstrappedData.slice(currentPage * pageLength, (currentPage + 1) * pageLength));
    currentPage++;
  };

  // Initialize data with first page load
  return $scope.nextPage();
});

Include the following template code:

<div ng-controller="listingController" infinite-scroll="nextPage()" infinite-scroll-distance="3">
  <ul>
    <li ng-repeat="item in listOfItems">{{item.name}}</li>
  </ul>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error: The function sort cannot be applied to the result of calling the calendar method on the moment object

I retrieve the data from this URL. I am looking to display the data sorted by a recent date. I attempted to use the map method to render the data and then proceeded to sort it based on the date, but encountered an error. To organize the dates, I made use ...

JavaScript: Reorder an array to alternate between largest and smallest elements, starting with the largest

When working with an array of integers that need to be sorted in a specific order, such as: [1, -1, -3, 9, -2, -5, 4, 8,] We must rearrange them so that the largest number is followed by the smallest number, then the second largest number followed by the ...

Chrome causing window.open to fail

I am currently working on developing a Cordova PhoneGap app and facing an issue with popping up a window for Facebook login after clicking a button. The popup works fine on iOS devices, but when I try debugging with Chrome, nothing happens even though th ...

AngularJS - Trouble loading directive

I'm facing some challenges with a custom directive I've created and it's not functioning as expected. Below is the code for my directive: angular .module('thermofluor') .directive('myCustomer', function() { return ...

Setting a default value in a dynamic dropdown using AngularJS

I could really use some assistance with my issue as I am fairly new to working with AngularJS. My dilemma is related to setting the default value in a select option when there is only one item available due to it being a dynamic select option. Though there ...

Prepending a string to the value using Angular's ngOptions

I've been working on creating a custom directive for Angular that includes a label and select element with necessary classes. This is what my directive code looks like: return { restrict: 'E', scope: { text: &a ...

What is the best method for transferring states between components?

When it comes to React JS, I am a beginner looking to develop a ToDo list application. In my project, I have the main page App.js, where I created the component MainBlock. This MainBlock component structures the layout into left and right sides. On the rig ...

Attaching dynamic data to a specific element within an array

I have successfully created a demo where elements can be dropped into a specific area and their top and left values are displayed. I have also added functionality to remove dropped items and move them between different blocks. However, I am encountering so ...

Storing the result of parsing JSON data into a global variable

$(function() { var countFromData = 0; getReminder(); alert(countFromData); }); function getReminder() { $.getJSON("<?=base_url()?>home/leavereminder", {}, function(data) { ...

When you use Greasemonkey to click a link embedded within the content

In need of assistance with clicking a dynamic link using Greasemonkey. The only static part of the code is the text 'Attack This Player'. The href attribute of the link changes depending on the page. Here is my current code: function click_elem ...

Node.js and Express facing challenge with Stripe checkout functionality

I am encountering an issue while attempting to integrate stripe into my checkout process. When I click on the checkout button, instead of being directed to the checkout page, I receive the following message: {"url":"https://checkout.stripe.c ...

What is the best way to transition all elements down while sliding a header up or down?

Is it possible to bring down the entire page when hovering over a header element using CSS, ensuring that the header overlaps nothing else on the page? If so, how can this be achieved? See an example of the header in action here: Thank you! ...

Facing a problem with Angular JS where the get method is resulting in a 405 error

Hey there, I have a service that is written with the following method: var GetData = function (token) { $http.defaults.headers.common['Authorization'] = 'Bearer ' + token; var response = $http.get(baseurl + "api/controller/sea ...

Exploring the concept of nested views in AngularJS's UI Router with multiple views integration

I am facing an issue with configuring multiple views on one page, where one view is nested within another. My code in app.js does not seem to be working properly. Below are the details: This is my index.html file <body ng-app="configuratorApp" > ...

Enhanced Fancybox Version 2 adjusts iframe width to fit content

I have been attempting to adjust the width of the iframe in fancybox v2 to fit my content properly. However, every time I try, the content appears too large within the iframe and requires horizontal scrolling to view it all. My goal is to see the entire wi ...

Iterate through a generic array to populate a table using ng-repeat

In the scenario I'm currently facing, I am working on creating a common reusable table structure using a directive. The goal is to display different JSON data in both the table header and body. Below is the controller code: angular.module('plun ...

The error prop in Material UI DatePicker does not function properly when combined with yup and react-hook-form

Currently, I am working on enhancing a registration form using tools such as yup, react-hook-form, and Material UI DatePicker/TextField. My goal is to include a date of birth field that validates whether the user is over 18 years old. Although the error me ...

Managing PHP multiple follow-up options in HTML select fields

My goal is to design a form that includes multiple follow-up select fields. These fields will be populated from an array with 3 elements: ID, Name, and followingID. The followingID corresponds to an ID in the array, helping us determine the hierarchical la ...

Delete auto-generated list using handlebars JS

I have successfully created a dynamic list using Handlebars.js and its template. However, I am now facing confusion on how to remove or delete items from the list using a function or specific code. As I am new to Handlebars, I would appreciate any help. ...

Encountering an error while trying to read a JSON file in AngularJS

I'm encountering an issue while trying to read a json file in my visual studio 2013 environment. The error message states: The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If ...