Welcome to JiKe DevOps Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
225 views
in Technique[技术] by (71.8m points)

javascript - Changing image in child component will update higher most html img tag in parent component

Video

I made a short 15 second Youtube video demonstrating the bug since its rather hard to explain here is video: https://www.youtube.com/watch?v=YXykw2oSh8E --- please ignore my terrible editing skills

Short Summary

I will summarize the error here: If I have two image tags and I am trying to change the image of the lower one that is located lower in the html file, the image on the higher most img tag will be changed as opposed to the one I selected even though the logic is in a seperate component instance

Code layout

In my code I have two <app-image-display> components stacked on top of one another. When I try to update the image of the one with the name of coverPhoto it will update the image in the one named profile. If I move the coverPhoto named instance higher in the html file than profile named instance and try to change profile it will update coverPhoto.

Parent

I have a parent component that looks like this:

....
<div *ngIf="company">
    <app-image-display name="profile" id="profile" #profile [image]="company.profileUrl" [uploadPath]='companyProfilePath' (imageUpdated)="updateImage($event, CompanyImage.PROFILE)"></app-image-display>
    
    <app-image-display name="coverPhoto" id="coverPhoto" #coverPhoto [image]="company.coverPhotoUrl" [uploadPath]='companyCoverPath' (imageUpdated)="updateImage($event, CompanyImage.COVER_PHOTO_URL)"></app-image-display>
</div>
.....

You can see it contains two separate instances of the same component called ImageDisplay. One of the instances is designed to handle a profile image and the other a cover photo. I put in temporary logic to show me which on is the cover photo just to be explicit as seen in the video. This component is designed to show the use the previously saved image then allow them to view a new image (tempImage) before saving it to the db. The ImageDisplayComponent looks like the following:

Image Display Html

<img [src]="image" width="200" *ngIf="!tempImage" height="200" class=" img-thumbnail" alt="Responsive 
image" onerror="this.src = 'TEMP_IMG_URL_GOES_HERE'">

<img [src]="tempImage" *ngIf="tempImage" width="200" height="200" class=" img-thumbnail" 
alt="Responsive image">
<span *ngIf="uploadPath.includes('cover')">Cover Image</span>
<app-image-picker *ngIf="!percentage" (imageSelected)="imageSelected($event) (tempImageSelected)="tempSelected($event)"></app-image-picker>

Image Display TS

And the .ts looks like this:

...
export class ImageDisplayComponent implements OnInit {
  @Output() imageUpdated: EventEmitter<string> = new EventEmitter();
  @Input() image: string = '';
  @Input() uploadPath: string
  tempImage: string;
  percentage: Observable<number>;
  selectedPictureFile: File;
  task: AngularFireUploadTask;



  constructor(
    private dbs: AngularFireStorage,
    private toastService: ToastService
  ) { }

  ngOnInit(): void {
    console.log(this.uploadPath)
  }


  imageSelected(image: File) {
    this.selectedPictureFile = image;
    this.fileUpload(this.uploadPath, this.selectedPictureFile);
  }

  async fileUpload(path: string, file: File): Promise<void> {
    const ref = this.dbs.ref(path);
    this.task = this.dbs.upload(path, file);
    this.percentage = this.task.percentageChanges();
    let imageUrl = '';
    from(this.task).pipe(
      switchMap(() => ref.getDownloadURL()),
      map((img) => imageUrl = img),
      finalize(() => delete this.percentage)
    ).subscribe(() => { 
      this.imageUpdated.emit(imageUrl)
    },(error) => {
      this.toastService.show(`${error.message}`, {
        delay: 3000,
        autohide: true
      });
    });
  }

  tempSelected(imageUrl: string) {
    this.tempImage = imageUrl;
  }
}
...

ImagePickerComponent Html

app-image-picker looks like the following:

<div style="margin: 5px">
<label for="file-upload" class="custom-file-upload">
   {{labelText}}
</label>
<input type="file" id="file-upload" (change)="onPictureSelected($event)" accept=".png, .jpg">
<div class="row">
    <button *ngIf="pictureSelected" class="btn btn-info m-1" [disabled]="!pictureSelected" (click)="uploadPicture()">
        Save
    </button>
    <button *ngIf="pictureSelected" class="btn btn-warn m-1" [disabled]="!pictureSelected" (click)="cancel()">
        Cancel
    </button>
</div>

ImagePickerComponent TS

This is what the onPictureSelected function looks like:

// image selection and verification.
  onPictureSelected(event) {
    this.selectedPictureFile = event.target.files[0] as File;
    const reader = new FileReader();
    reader.readAsDataURL(this.selectedPictureFile);
    if (!this.imageService.isImage(this.selectedPictureFile.name)) {
      this.pictureSelected = false;
    } else if (!this.imageService.isAllowedSize(this.selectedPictureFile.size)) {
      this.pictureSelected = false;
    } else {
      // tslint:disable-next-line:no-shadowed-variable
      reader.onloadend = (event: any) => {
        if (event.target) {
          this.selectedPictureURL = event.target.result;
          this.tempImageSelected.emit(this.selectedPictureURL);
        }
      };
      this.pictureSelected = true;
    }
  }

I am on Angular version 9.0.3


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

Please log in or register to answer this question.

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to JiKe DevOps Community for programmer and developer-Open, Learning and Share
...