子组件向父组件发出的事件的奇怪行为

时间:2019-01-05 14:29:47

标签: html arrays angular typescript events

我正在使用EventEmitter从子组件向父组件发送URLimage数组。

孩子的发射器:

@Output() images  = new EventEmitter<string[]>();

父母的html:

<app-file-upload (images)="onLoadedImages($event)"></app-file-upload>

其中<app-file-upload>是孩子。

父级的OnLoadedImages()函数

  onLoadedImages(images: string[]) {
    console.log(images);
    console.log(images[0]);
  }

控制台输出: image of console output

当在控制台输出中看到images[0]包含数据以及如何访问undefined数据时,为何images: string[]给出@Component({ selector: 'app-file-upload', templateUrl: './file-upload.component.html', styleUrls: ['./file-upload.component.css'] }) export class FileUploadComponent implements OnInit { loadedImagesAsURL = []; @Output() images = new EventEmitter<string[]>(); constructor() { } ngOnInit() { } onFileSelected(event) { const filesList = event.target.files; for (const file of filesList) { const reader = new FileReader(); reader.onload = (e: any) => { this.loadedImagesAsURL.push(e.target.result); }; reader.readAsDataURL(file); } this.images.emit(this.loadedImagesAsURL); } }

编辑:

@Colby Hunter作为评论的答案,以下是孩子的内容:

<div class="text-center" *ngIf="loadedImagesAsURL.length>0" style="height: 300px; overflow: auto;">
  <span *ngFor="let image of loadedImagesAsURL">
    <img style="width: 100%;" height="400" src="{{image}}">
  </span>
</div>
<div>
  <input type="file" multiple (change)="onFileSelected($event)" style="display: none;" #fileUpload>
  <button type="button" class="btn btn-secondary" (click)="fileUpload.click()">Wybierz zdjęcia</button>
</div>
{{1}}

1 个答案:

答案 0 :(得分:2)

浏览器的控制台进行延迟评估。尝试做:

console.log(JSON.stringify(images));
console.log(images[0]);

您会看到它是一个空数组。

在您这种情况下,当您手动单击“图像”的控制台日志时,文件将被加载并看到内容。

由于您需要读取所有文件并进行最终发射,因此可以使所有文件读取事件都可观察到, 一旦所有Obsevables完成,就发出您的数组。

public onFileSelected(event): void {
    let loadenedObs = this._createFileReaderObs(event);
    forkJoin(...loadenedObs).subscribe(() => {
        // all the files are read, emit the array now.
        this.images.emit(this.loadedImagesAsURL);
   })
}

private _createFileReaderObs(event): [] {
    let obsArr = [];
    const filesList = event.target.files;
    for (const file of filesList) {
      const reader = new FileReader();

      const loadenedEventObs = fromEvent(reader, 'loadend').pipe(
            tap(() => {
                this.loadedImagesAsURL.push(reader.result);
            }),
            take(1)      // take one event to complete the Observable
        );

      obsArr.push(loadenedEventObs);    // create an array of loadened observables.
      reader.readAsDataURL(file);
    }
    return obsArr;
}