I have an Angular Directive that is used for loading images in a lazy way. The code is the following:
import { Directive, ElementRef } from '@angular/core';
@Directive({ selector: '[appImgLazy]' })
export class LazyLoadingImgDirective {
constructor({ nativeElement }: ElementRef<HTMLImageElement>) {
const supports = 'loading' in HTMLImageElement.prototype;
if (supports) {
nativeElement.setAttribute('loading', 'lazy');
}
}
}
I want to display a placeholder image while the actual image is being loaded and, once it has finished, replace the placeholder with the actual image. I've tried the approach suggested in this answer but it doesn't work properly. If I use Chrome DevTools to inspect the network traffic it seems it's requesting the image everytime, although it has been already loaded. Also, the placeholder is never shown.
The complete directive with modifications:
import {
Directive,
Attribute,
Renderer2,
ElementRef,
HostListener } from '@angular/core';
@Directive({
selector: '[appImgLazy]'
})
export class LazyLoadingImgDirective {
constructor(
@Attribute('loader') public loader: string,
@Attribute('onErrorSrc') public onErrorSrc: string,
private renderer: Renderer2,
private el: ElementRef,
{ nativeElement }: ElementRef<HTMLImageElement>) {
const supports = 'loading' in HTMLImageElement.prototype;
if (supports) {
nativeElement.setAttribute('loading', 'lazy');
}
this.renderer.setAttribute(this.el.nativeElement, 'src', this.loader);
}
@HostListener('load') onLoad() {
this.renderer.setAttribute(this.el.nativeElement, 'src', this.el.nativeElement.src);
}
@HostListener('error') onError() {
this.renderer.setAttribute(this.el.nativeElement, 'src', this.onErrorSrc);
}
}
Usage:
<img
appImgLazy
onErrorSrc="src/assets/images/not-found-image.png"
loader="src/assets/images/placeholder.png"
[src]="product.cover">
My package.json
dependencies:
"dependencies": {
"@angular/animations": "~9.1.6",
"@angular/cdk": "^9.2.3",
"@angular/common": "~9.1.6",
"@angular/compiler": "~9.1.6",
"@angular/core": "~9.1.6",
"@angular/forms": "~9.1.6",
"@angular/localize": "^9.1.12",
"@angular/platform-browser": "~9.1.6",
"@angular/platform-browser-dynamic": "~9.1.6",
"@angular/router": "~9.1.6",
"@ngx-translate/core": "^12.1.1",
"@ngx-translate/http-loader": "^4.0.0",
"bootstrap": "^4.4.1",
"cookieconsent": "^3.1.1",
"messageformat": "^2.3.0",
"ngx-cookieconsent": "^2.2.3",
"ngx-device-detector": "^1.4.5",
"ngx-toastr": "^12.0.1",
"ngx-translate-messageformat-compiler": "^4.7.0",
"rxjs": "~6.5.4",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
},