Applying same directive to many divs in a single component, attaches event listener of that directive to only the last one

Issue

I have 50 divs on a single component. I am making a directive named “lazyload”. Then I am applying this directive to all those divs. In the onInit of “lazyload” directive, I have registered for scroll event. The eventlistener function of scroll is supposed to check if this div(in my case, all these 50 divs where this directive is applied) is inside viewport or not, and then do few operations on that particular div. But it seems that this scroll event is registered only for the last div of my view.

My component’s template:

<div class="product-container" *ngFor="#product of allProducts">
            <div class="product-image" 
            [lazyLoadImage]="product.image" >
            </div>
            <div class="product-desc">
                <p>{{product.name}}</p>
                <p> <span>{{product.price | currency:'INR':true}}</span> <span>{{product.monthDiff + " months"}}</span> </p>
            </div>
        </div>

The directive “lazyLoadImage” is:

@Directive({
    selector: '[lazyLoadImage]'
})
export class LazyLoadImgDirective {

    private _el: HTMLElement;

    private _canLoadImage: boolean = false;

    private _imgUrl: string;

    @Input()
    set lazyLoadImage(v){
        this._imgUrl = v;
        if(v){
            this.attachEvent()
        }
    }

    constructor(el: ElementRef, private _utils:UtilServices) { this._el = el.nativeElement;}

    private _loadingDone: boolean = false;

    loadImage(){
      //some operations
    }

    attachEvent() {
        console.log("inside image load dir");
        var self = this;
        setTimeout(() => self.loadImage(), 1);
        window.onscroll = (event) => {
            console.log("scrolling intercepted for: "+self._imgUrl);//log is shown only for the last element where this directive is applied
            if (!self._loadingDone){
                setTimeout(() => self.loadImage(), 1);
            }
        }
    }
}

The event listener for scroll is working only on the last product in the iteration.

Solution

As @yurzui said you are overriding the event handler.

Plunker example

I also fixed some other issues in your code (no need for self = this if you use => and a few others).

ElementRef is null because there is no provider for , private _utils:UtilServices. Removing this parameter makes ElementRef being set.

Answered By – Günter Zöchbauer

Answer Checked By – Marie Seifert (AngularFixing Admin)

Leave a Reply

Your email address will not be published.