使用 Angular 上传文件的嵌套数组

nested array for file upload with angular

提问人:cng 提问时间:10/10/2023 最后编辑:cng 更新时间:10/10/2023 访问量:48

问:

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

enter image description here有什么想法吗?非常感谢!

演示:stackblitz

arrays angular 文件 嵌套 上传

评论


答:

1赞 Yong Shun 10/10/2023 #1

从您的 StackBlitz 链接中,您正在迭代数组并共享相同的 .因此,这导致图像在上传时也会显示在其他类别/类型中。updateDocFormArray

您需要嵌套数组来分隔不同类型的图像,并且您的 Reactive Form 结构应为:

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

总之:

  1. 插入图像时,您需要类别类型 () 的索引才能将图像添加到正确的 FormGroup 中。photosRootIndex

  2. 删除图像时,需要类别类型 () 和图像索引 () 的索引才能正确删除图像。photosRootIndexphotosChildIndex

  3. 迭代数组并将每个类别添加到数组中。uploadDocFormGroupphotos

<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