Hone logo
Hone
Problems

Implementing Virtual Scrolling in Angular

Virtual scrolling is a performance optimization technique used to render very long lists efficiently. Instead of rendering the entire list at once, it only renders the items currently visible in the viewport, significantly reducing the DOM size and improving performance, especially for lists with thousands of items. This challenge asks you to implement a basic virtual scrolling component in Angular.

Problem Description

You need to create an Angular component that displays a long list of items using virtual scrolling. The component should only render the items that are currently visible within the viewport, dynamically loading and unloading items as the user scrolls. The component should accept an array of data as input and display each item in a template. The goal is to demonstrate the core principles of virtual scrolling, focusing on efficient DOM manipulation and responsiveness.

Key Requirements:

  • Data Input: The component should accept an array of data items as input. Each item should have a unique identifier (e.g., id).
  • Viewport Calculation: The component should determine the visible range of items based on the viewport size and the height of each item.
  • Dynamic Rendering: Only the items within the visible range should be rendered in the DOM.
  • Scrolling Handling: The component should listen for scroll events and update the rendered items accordingly.
  • Item Tracking: The component should keep track of the rendered items to efficiently update the DOM when the viewport changes.
  • Template: The component should use a template to display the data items.

Expected Behavior:

  • When the component is initialized, only the items visible in the initial viewport are rendered.
  • As the user scrolls up or down, new items should be dynamically added to the DOM, and items that are no longer visible should be removed.
  • The scrolling should be smooth and responsive, even with a large number of items.
  • The component should handle cases where the list is shorter than the viewport.
  • The component should handle cases where the list is much longer than the viewport.

Edge Cases to Consider:

  • Empty Data Array: Handle the case where the input data array is empty.
  • Variable Item Height: While this challenge assumes consistent item height for simplicity, consider how the component would adapt to variable item heights in a more advanced implementation.
  • Initial Viewport: Consider how the initial viewport is determined (e.g., top of the list).
  • Performance with Very Large Datasets: While not the primary focus, be mindful of potential performance bottlenecks with extremely large datasets.

Examples

Example 1:

Input: data = [{id: 1, name: 'Item 1'}, {id: 2, name: 'Item 2'}, {id: 3, name: 'Item 3'}, {id: 4, name: 'Item 4'}, {id: 5, name: 'Item 5'}]
Viewport Height: 200px
Item Height: 50px
Output: Only items with id 1, 2, 3, and 4 are rendered.
Explanation: The viewport can fit 4 items (200px / 50px).  Therefore, only the first four items are rendered.

Example 2:

Input: data = [{id: 1, name: 'Item 1'}, {id: 2, name: 'Item 2'}, {id: 3, name: 'Item 3'}]
Viewport Height: 300px
Item Height: 50px
Output: All three items (1, 2, and 3) are rendered.
Explanation: The viewport can fit 6 items (300px / 50px), but there are only 3 items in the data array.  All items are rendered.

Example 3:

Input: data = Array(1000).fill({id: i, name: `Item ${i}`})
Viewport Height: 400px
Item Height: 30px
Output: Approximately 13 items are rendered at any given time (400px / 30px).  As the user scrolls, items are dynamically added and removed.
Explanation: The viewport can fit approximately 13 items. The component dynamically renders only those items within the viewport.

Constraints

  • Angular Version: Use Angular 14 or later.
  • Item Height: Assume a consistent item height of 50px for simplicity. (This can be a parameter to the component in a more advanced implementation).
  • Data Structure: Each data item must have a unique id property (number).
  • Performance: The scrolling should be smooth and responsive. Avoid unnecessary DOM manipulations.
  • No External Libraries: Do not use external libraries for virtual scrolling (e.g., ngx-virtual-scrolling). The goal is to implement the core logic yourself.

Notes

  • Consider using ngAfterViewInit to calculate the initial viewport range.
  • Use Renderer2 for efficient DOM manipulation if needed.
  • The trackBy function in *ngFor is crucial for efficient updates.
  • Focus on the core logic of virtual scrolling: calculating the visible range and dynamically rendering items. Styling and advanced features are not required for this challenge.
  • Think about how to handle the case where the data array is very large (e.g., thousands or millions of items).
Loading editor...
typescript