Angular - 用于文件上传的嵌套数组

问题描述 投票:0回答:1

我会尝试用 Angular 构建一个文件上传器。需要上传不同类型的文件。每个按钮可以上传多个文件。现在,我无法区分文件类型。当我上传文件时,它会以不同的文件类型显示相同的文件。我想把它分开

有什么想法吗?非常感谢!

演示:stackblitz

arrays angular file-upload nested
1个回答
1
投票

从您的 StackBlitz 链接中,您正在迭代

updateDoc
数组并共享相同的
FormArray
。因此,上传时图像中的结果也会显示在其他类别/类型中。

您需要嵌套数组来分隔不同类型的图像,您的反应式表单结构应如下:

{
  'text_input': '',
  'photos': [
    {
      'title': 'Apple',
      'photos': []
    },
    {
      'title': 'orange',
      'photos': []
    }
  ]
}

简而言之:

  1. 插入图片时,需要类别类型的索引(

    photosRootIndex
    )才能将图片添加到正确的FormGroup中。

  2. 删除图片时,需要类别类型索引(

    photosRootIndex
    )和图片索引(
    photosChildIndex
    )才能正确删除图片。

  3. 迭代

    uploadDoc
    数组并将每个类别作为
    FormGroup
    添加到
    photos
    数组中。

<div class="container">
  <div class="row">
    <div class="col-xs-12 col-sm-10 col-md-8 col-md-offset-2 col-sm-offset-1">
      <form [formGroup]="demoForm" (ngSubmit)="onSubmit()">
        <div formArrayName="photos"
          *ngFor="let photo of photos.controls; let i = index">
          <ng-container [formGroupName]="i">
            {{ uploadDoc[i].id }} {{ uploadDoc[i].title }}
            <div class="form-group">
              <input
                type="file"
                class="custom-file-input form-control"
                id="files"
                multiple
                (change)="detectFiles($event, i)"
                accept="image/x-png,image/jpeg"
              />
            </div>


            <div class="images-preview mt-2" *ngIf="photoCategoryPhotos(i).length">
              <div class="row">
                <div
                  class="col-md-6 col-lg-3 col-xl-2"
                  formArrayName="photos"
                  *ngFor="let photo of photoCategoryPhotos(i).controls; let j = index"
                >
                  <div class="card mb-3" [formGroupName]="j">
                    <button
                      type="button"
                      (click)="removePhoto(i, j)"
                      class="btn btn-danger remove-btn"
                    >
                      x
                    </button>
                    <img
                      [src]="photo.controls.url.value"
                      class="card-img-top"
                      alt="Image Preview"
                    />
                  </div>
                </div>
              </div>
            </div>
          </ng-container>
        </div>

        <button class="btn btn-primary" type="submit">Submit</button>
      </form>
    </div>
  </div>
</div>
constructor(private formBuilder: FormBuilder) {
  this.demoForm = this.formBuilder.group({
    text_input: ['', Validators.required],
    photos: this.formBuilder.array([]),
  });

  for (let doc of this.uploadDoc) {
    (this.demoForm.controls.photos as FormArray).push(
      this.createNestedPhotoForm(doc.title)
    );
  }
}

...

photoCategoryPhotos(photosRootIndex: number): FormArray {
  return (this.photos.controls[photosRootIndex] as FormGroup).controls
    .photos as FormArray;
}

createNestedPhotoForm(title: string): FormGroup {
  let photoCategoryForm = this.formBuilder.group({
    title: [title],
    photos: this.formBuilder.array([]),
  });

  return photoCategoryForm;
}

detectFiles(event, photosRootIndex) {
  let files = event.target.files;
  if (files) {
    for (let file of files) {
      let reader = new FileReader();
      reader.onload = (e: any) => {
        console.log('e.target.result', e.target.result);
        this.photoCategoryPhotos(photosRootIndex).push(
          this.createItem({
            file,
            url: e.target.result, //Base64 string for preview image
          })
        );
      };
      reader.readAsDataURL(file);
    }
  }
}

removePhoto(photosRootIndex, photosChildIndex) {
  this.photoCategoryPhotos(photosRootIndex).removeAt(photosRootIndex);
}

演示@StackBlitz

© www.soinside.com 2019 - 2024. All rights reserved.