Angular

Lazy Loading in a Angular Carousel

Today’s tech tip is almost too primitive to mention. However, on second glance, it shows how to use Angular efficiently. I reckon there’s a general pattern there, even if I haven’t been able to distill it yet to make it a textbook lesson.

Setting the stage

Consider a carousel, such as the first demo at our BootsFaces showcase. It displays three images. At every point in time, only one of the three images is shown, unless you click to show the next image. In that case, the next image starts to slide into view, replacing the old image.

Things get ugly if we’ve got hundreds of images. They also get ugly if the carousel is used to implement a wizard. Chances are that the content of the second page of the wizard depends on the input provided on the first page of the wizard. In other words, the second page can’t be rendered at load time. As you can imagine, our use case was a combination of these two options.

Restricting the solution space

For the sake of simplicity, let’s assume we’re using the Carousel widget of ngx-bootstrap. The idea works in many other situations, too, both with other carousel components and with completely other UI components, such as accordions. But writing is a lot easier if we pick one concrete example instead of staying aloft in the realm of abstractions.

Naive implementation

By default, the ngx-bootstrap carousel is defined by jotting down every slide like so:

<carousel>
  <slide>
    <img src="1.jpg">
  </slide>
  <slide>
    <img src="2.jpg">
  </slide>
  <slide>
    <img src="3.jpg">
  </slide>
</carousel>

This approach works well with a handful of images, but remember, we’re dealing with hundreds of images. The browser analyzes and renders the entire HTML page. Most likely, the image of the first slide is loaded first, but there are no guarantees. Plus, maybe we don’t want to start with the first slide, but with slide 50. In this case, prepare to fight with long load times.

Of course, usually, you don’t jot down each slide individually, especially in the case of hundreds of slides. In real-world applications, the code looks like so:

<carousel>
  <slide *ngFor="let slide of slides; let currentIndex = index;">
    <img src="{{currentIndex}}.jpg">
  </slide>
</carousel>

Rendering only what can be displayed

Of course, the way to reduce the load time is ridiculously simple: stop loading the images which aren’t needed now. You can load them later when the user scrolls to the next page.

Using good old jQuery, that’s quite a challenge. You’d have to insert the image into the DOM each time the carousel scrolls to a new page. Angular makes this task very simple. It’s simply adding an *ngIf directive:

<carousel (activeSlideChange)="activeIndex=$event">
  <slide *ngFor="let slide of slides; let currentIndex = index;">
    <img src="{{currentIndex}}.jpg" *ngIf="currentIndex = activeIndex">
  </slide>
</carousel>

This code ensures that only one image is loaded at load time. The other images are loaded after sliding into view. That’s a huge improvement. Considering that the next image is already displayed when it’s sid into view, the optimization has gone too far. You should also load the next and the previous image. But you get the idea: that’s a simple tweak of the *ngIf statement.

For the sake of completeness, I should display the Angular component class. But I’ll drop it because it isn’t really important. Suffice it to say it has two variables: slides is the list of images, and activeIndex is the index of the currently displayed slide.

By the way, I didn’t test the source codes of this article. I’ve implemented the real (and working) code a couple of days ago, and the source codes listed here are a simplified version of what I remember to have programmed. So take the source codes with a grain of salt, and please leave a comment if you spot an error. This article is more about concepts than being a precise walk-through.

Wrapping it up

Angular simplifies many problems that used to be hard. In this case, it’s lazy loading. Under normal circumstances, implementing lazy loading is almost always a pain in the – you know where. Using Angular, sometimes it’s simply a matter of cleverly using the *ngIf directive.

Like I’ve mentioned above, I’m sure this can be generalized to a recipe. I just don’t know yet how to do it. If you’ve got an idea, don’t hesitate to drop a suggestion in the comments sections below.

One thought on “Lazy Loading in a Angular Carousel

Leave a Reply

Your email address will not be published.