tjoskar / ng-lazyload-image

🖼 A small library for lazy loading images for Angular apps with zero dependencies
https://naughty-bose-ec1cfc.netlify.com
MIT License
762 stars 142 forks source link

Documentation on scrollObservable #350

Closed calbear47 closed 5 years ago

calbear47 commented 6 years ago

I wanted throw this issue up incase others have struggled to work with scrollObservable. For my particular use case, I had a reusable component that I was using in many different situations in the app. At times, I wanted to load the thumbnail of the card on scroll, but others times I wanted to load in a horizontal slider.

Furthermore, the thumbnail just showed the first image of a slideshow of images that could be paged through on the card. I wanted each image in the slideshow to lazy load as well.

I wanted to share some of the code I used to accomplish this in hopes that it could help someone else.

Setup in ngOnInit

this.loadObservable = new Subject<string>();
const targetEl = this.scroller.scrollContainers.entries().next().value[0].getElementRef();  // I have only 1 scrolling container in my app. 
this.scrollTargetObservable  = fromEvent(targetEl.nativeElement, 'scroll');
this.loadImage = combineLatest(this.scrollTargetObservable, this.loadObservable.pipe(startWith('scroll')));

Template:

<div class="image-overlay" #imageOverlay (click)="itemSelected.emit()" [defaultImage]="'https://<image-cdn>.net/'+images[startingIndex]+'?auto=format&w=' + width + '&h=auto&q=1&blur=100'" [lazyLoad]="'https://<image-cdn>.net/'+images[startingIndex]+'?auto=format&w=' + width + '&h=auto&q=50'" (swipeleft)="next($event, 'swipe')" (swiperight)="prev($event, 'swipe')" [scrollObservable]="loadImage"></div>

Call this method whenever I need to load the thumbnail, or load the active image in my slideshow.

  loadThumb() {
    setTimeout(() => {
      this.loadObservable.next('scroll');
      this.cd.detectChanges();
    }, 0);
  }

You might not need to wrap yours in a setTimeout or detectChanges...depending on your use case.

lalitmee commented 6 years ago

Hey @calbear47, if you can provide all the methods from where you are importing then it would be great. 😇

tjoskar commented 6 years ago

@lalitmee

Subject, fromEvent and combineLatest is imported from rxjs: import { .Subject, fromEvent, combineLatest } from 'rxjs'

this.cd is ChangeDetectorRef. You can get it from the DI:

import { Component, ChangeDetectorRef } from '@angular/core';

@Component({
  ...
})
export class MyComponent {
  cd: ChangeDetectorRef

  constructor(cd: ChangeDetectorRef) {
    this.cd = cd
  }
}

I'm however not sure what this.scroller is. Can you elaborate @calbear47?

calbear47 commented 6 years ago

this.scoller is an instance of the scroller service provided by Angular Material. You can get it from DI just like any other service.

Scroller API Docs

lalitmee commented 6 years ago

thank you, guys. I solved my problem by using offset :smiley:

fotoguy42 commented 5 years ago

For me, just calling next in the setTimeout fixed my issues of images not loading when I either hide elements, or changed the sizes. I didn't have to use the change detection. setTimeout(() => { this.loadObservable.next('scroll'); }, 0);