1

I have a html code like this with template reference variable for app-image-upload-component

<div *ngFor="let image of images"; let i = index>
  <app-image-upload #imageUpload (click)="uploadImage(i)" (image)="setImageData($event, i)">
    <img src="assets/img/camera-img.png" alt="img">
    <h4>Upload Image</h4>
  </app-image-upload>
</div>

Then in my typescript code, i am doing something like this

@ViewChild('imageUpload') imageUpload: ImageUploadComponent;

uploadImage(index) {
  console.log('index', index);
  this.imageUpload.showImageBrowseDlg();
}

When i fire click event on app-image-upload, then it always shows index value 0, no matter what is the index of *ngFor.

I know this is happening because #imageUpload is refrencing only to the first element of ngFor, so is there a way to reference all elements of *ngFor differently and to use them, as required in my code.

chandradot99
  • 3,616
  • 6
  • 27
  • 45

3 Answers3

1

You can use ViewChildren which has a QueryList of components.

import {ViewChildren,QueryList} from '@angular/core';
    @ViewChildren('imageUpload') imageUploads: QueryList<ImageUploadComponent>;

    uploadImage(index) {
      console.log('index', index);
      this.imageUploads.find((imgUpld,i)=>{
          return index == i;
      }).showImageBrowseDlg();
    }
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
1

Finally I figured out how to solve this issue, instead of @ViewChild, i can use @ViewChildren and can do something like this.

@ViewChildren(ImageUploadComponent) imageUploadChildren: QueryList<ImageUploadComponent>;

#Subscribe for changes, so that if we delete any children, then it must new array.

ngAfterViewInit() {
  this.imageUploadChildrenArray = this.imageUploadChildren.toArray();
  this.imageUploadChildren.changes.subscribe(childern => {
  this.imageUploadChildrenArray = childern.toArray();
});

}

uploadImage(index) {
  this.imageUploadChildrenArray[index].showImageBrowseDlg();
}
chandradot99
  • 3,616
  • 6
  • 27
  • 45
0

You can pass a #ref to handle function. Make sure that u export your upload directive with exportAs and assign a ref to it. See an example here:

https://plnkr.co/edit/BN2dreniteQag82h28BC?p=preview

  @Directive({
    selector: '[upload]',
    exportAs: 'upload'
  })
  export class Upload {
    static i =0;
    constructor() {
      this.instanceI = Upload.i++;
      console.log('upload');
    }
  }

  @Component({
    selector: 'my-app',
    template: `
      Last handled upload {{last}}
      <div *ngFor="let i of items">
        <h2 upload #uploadRef="upload" (click)="handle(uploadRef)">Hello {{i}}</h2>
      </div>
    `,
  })
  export class App {
    items = ['a', 'b', 'c'];

    constructor() {
    }

    handle(uploadRef) {
      console.log(uploadRef);
      this.last = uploadRef.instanceI;
    }
  }
Julia Passynkova
  • 17,256
  • 6
  • 33
  • 32