2

I have four components, the parents componets.html looks like

<div class="main">
    <div class="column-left">
        <app-document-info></app-document-info>
    </div>
    <div class="column-center" style="float:left">
        <app-document-scan></app-document-scan>
    </div>
</div>

Document-Scan component also contains component inside this is some snippet code for that component (Document-Nested)

<div class="btnGrp">
  <input type="file" name="img" multiple (change)="onChange($event)">
</div>

  public onChange(event: Event) {
    this.loadFiles();
  };

  loadFiles() {
    let files = event.target['files'];
    this.allFiles = files.length;

    for (var i = 0; i < files.length; i++) {
      let fileReader = new FileReader();
      fileReader.onload = () => {
        let infoFile: string = fileReader.result;
        let obj: fileStructure = {
          name: files[this.loadedFiles].name,
          data: fileReader.result,
          type: files[this.loadedFiles].type
        }
        this.listImages.push(obj);
        this.loadedFiles++;
        this.loadImage();
      }
      if (fileReader && files && files.length) {
        fileReader.readAsDataURL(files[i]);
      }
    }
  }

 loadImage() {
      this.imageService.setImages(this.listImages);
      this.imageLoadedEvent.emit(this.isClickedFileUploader);
}

My component Document-info i have some method that I would execute when method loadFiles() from document-scan is finished or pass data to this component that i inject in loadImage() method using service

This is my service

    export class ImageService {
    isClicked: boolean = false;    
    listImages: fileStructure[] = [];
    bodyContent;

    setBodyRes(res) {
        this.bodyContent = res;
    }

    getBodyRes() {
        return this.bodyContent;
    }

    setImages(imageList: fileStructure[]) {
        this.listImages = imageList;
    } 

    getImages(): fileStructure[] {
        return this.listImages;
    }
}

How to pass data or inform some method that finish execute between component Document-Nested that is inside Document-Scan and Document-Info. Document-Scan and Document-Info are sibling ?

Walter White
  • 976
  • 4
  • 12
  • 29

3 Answers3

3

You can communicate between components using a number of different methods, which you can find out more info here: https://angular.io/guide/component-interaction

In your case, you may want the Document-Scan to expose an event:

@Output() onLoadFilesCompleted = new EventEmitter<DataType>();

The parent would then need to subscribe to it like this

<app-document-scan [onLoadFilesCompleted]="doSomething()"></app-document-scan>

You could also have an injected service that allows communication between a number of different components, which might be easier for you if things are getting complicated.

Ross Scott
  • 1,690
  • 9
  • 16
  • I would that my Nested Componet in Document-Scan pass Data to component Document-Info. I should use parent component and in Document-Info i should use @Input. If is poosible that Nested-Componet inform Document-Info that some method in this component is finished. – Walter White Aug 24 '17 at 13:25
  • Yes, you either need to use a parent and @Input, or use a service shared between bother components which I think is slightly cleaner in your case. – Ross Scott Aug 24 '17 at 13:29
2

Use @Output decorator. You have not posted code for you components, so I'll assume the names:

In your <app-document-scan> component:

import { Output, EventEmitter } from '@angular/core';
...
export class DocumentScanComponent {
    @Output() filesLoaded: EventEmitter<boolean> = new EventEmitter();

    loadFiles() {
        let files = event.target['files'];
        this.allFiles = files.length;

        for (var i = 0; i < files.length; i++) {
          let fileReader = new FileReader();
          fileReader.onload = () => {
            let infoFile: string = fileReader.result;
            let obj: fileStructure = {
              name: files[this.loadedFiles].name,
              data: fileReader.result,
              type: files[this.loadedFiles].type
            }
            this.listImages.push(obj);
            this.loadedFiles++;
            this.loadImage();

            // Emit the event here
            this.filesLoaded.emit(true);
          }
          if (fileReader && files && files.length) {
            fileReader.readAsDataURL(files[i]);
          }
        }
      }
}

change you parents componets.html to following:

<div class="main">
    <div class="column-left">
        <app-document-info #documentInfo (filesLoaded)="onFilesLoaded()"></app-document-info>
    </div>
    <div class="column-center" style="float:left">
        <app-document-scan></app-document-scan>
    </div>
</div>

.. and in your parents components.ts define the method:

import {Component,ViewChild} from '@angular/core';

@Component({
    ....
})
export class ParentComponent {
    @ViewChild('documentInfo) documentInfo: DocumentInfoComponent;

    onFilesLoaded(){
        documentInfo.someMethodYouWantToCall();
    }
}
FAISAL
  • 33,618
  • 10
  • 97
  • 105
1

You can achieve this with an @Input.

The parent component can tell the child what files are loaded (@Input of child).

And with an @Ouput you can tell the parent you finish or pass files back.

After this the parent can do another @Input to your second child with all the files.

Read https://angular.io/guide/component-interaction .

Swoox
  • 3,707
  • 2
  • 21
  • 32