Avoid image reload in [src] in Angular
Asked Answered
T

3

11

I have an app which shows a list of users with a profile picture. When I update a value for this user the image gets reloaded as the observable list emits all data again. How can I avoid this?

<div *ngFor="let user of users">
<img [src]="user.profilepic"/> {{user.name}} <button (click)="updateUser(user)">Update</button>
</div>

TS :

this.userProvider.getUserList()
      .distinct()
      .subscribe(data => {
        this.users = data
      })

I hoped this distinct() function would do the job but no success.. The app is made with ionic 3 in combination with firebase realtime database data and firebase storage pictures downloaded with the public url

EDIT

3 years later I am facing the same issue in another app... Everytime something comes in from my Observable, the images blinks (so I assume it refreshes?)

enter image description here

Transhumance answered 30/1, 2018 at 21:25 Comment(10)
Have you tried checking to see if the value exists before you assign the value again?Jauch
Does it actually matter? The image should be pulling from cache if it has previously been displayed.Lindahl
@Lindahl it does pull from cache in browser, but not in my cordova app. App is built with ionic but this doesn't matter for this problem I guess..Transhumance
@Nicholas Can you please show how to do that? I am trying to keep a catalog as an Object with image urls but I guess the reload would still happenTranshumance
Well you might try two approaches. You can check in the view by using an angular expression , or possibly just check in the subscribe function to see if the user data you need exists already before you attach it to this.Jauch
I would check it in the subscribe function but the problem is I do want to see other user data changes like user.name reflected in my app. This user.name gets updated by the button click and I see this change immediately.Transhumance
@Transhumance did you find a fix for this issue?Belie
Unfortunately I didn't. The issue still occurs in my app...Transhumance
@Transhumance ok thanks!Belie
try implement trackBy betterprogramming.pub/… it'll do a shallow compare and determine if a node need re-renderingExplain
I
10

You need to use trackBy.

<div *ngFor="let user of users; trackBy: trackBy">
    <img [src]="user.profilepic"/> {{user.name}} <button (click)="updateUser(user)">Update</button>
</div>

Then in your component define:

public trackBy(index, user) {
    return user.id; // or any other identifier
}

This will prevent Angular of creating elements in DOM.

Itching answered 20/5, 2021 at 5:29 Comment(0)
C
0
<div *ngFor="let user of users">
<img [src]="user.profilepic"/> {{user.name}} <button (click)="updateUser(user)">Update</button>
I am assuming... after the successful update you are trying to fetch all user list again
updateUser(user){
//after the successful update
        this.userProvider.getUserList()
              .distinct()
              .subscribe(data => {
                this.users = data
             })
}

instead of fetching on the successful update ... you can update only one user (the updated user) in list

updateUser(user){
    //after the successful update

    this.userlist.find(a=> a.id== user.id).name = user.name;

    //can update whatever field you have uoadated
}
Collin answered 23/5, 2021 at 3:38 Comment(0)
W
-1

You've to update individual user object as reassigning users array to refresh the html

this.userProvider.getUserList()
      .distinct()
      .subscribe(data => {
        if(!this.users) {
         this.users = data
        }
        else {
           for(let user of data) {
                 /* TODO find the user in this.users array & updated required properties, if user not found add it to this.users array*/ 
           }
        }
      })
Wounded answered 20/5, 2021 at 5:25 Comment(2)
I didn't try this solution because the way Vova Bilyachat solved it is really clean to implement. Thanks for the effort thoughTranshumance
This wont help, i would even say it bad approach. Keep data immutableItching

© 2022 - 2024 — McMap. All rights reserved.