web-dev-qa-db-fra.com

téléchargement de plusieurs fichiers avec des formes réactives angulaires

J'essaie de créer un formulaire dans Angular 6 qui offre une boîte de sélection de fichier permettant à l'utilisateur de sélectionner plusieurs fichiers (Stackblitz: https://stackblitz.com/edit/angular-yjummp ).

Le modèle ressemble à:

<form [formGroup]="form">
    <input id="files" formControlName="files" type="file" accept="image/*,video/*" multiple (change)="onFilesChanged($event)"/>
</form>

Je construis la forme dans TypeScript comme ceci:

  public form = new FormGroup({
    files: new FormControl('')
  });

  public onFilesChanged(event: any): void {
    console.log(event.target.files);
    console.log(this.form.value);
  }

Désormais, dans le gestionnaire onFilesChanged, les fichiers sélectionnés peuvent être correctement extraits de l'événement en accédant à event.target.files (évidemment), mais l'impression de la valeur du formulaire n'imprime qu'un seul fichier. J'ai essayé plusieurs façons d'utiliser FormArray également, mais je n'ai pas eu de chance jusqu'à présent.

Des idées? Merci beaucoup!

5

Vous trouverez ci-dessous un exemple illustrant comment j'ai réalisé plusieurs fichiers d'entrée de téléchargement de photos via des formulaires réactifs angulaires.

public demoForm: FormGroup;

constructor(private formBuilder: FormBuilder) { 
    this.demoForm = this.formBuilder.group({
       text_input: ['', Validators.required],
       photos: this.formBuilder.array([])
    });
}

// We will create multiple form controls inside defined form controls photos.
createItem(data): FormGroup {
    return this.formBuilder.group(data);
}

//Help to get all photos controls as form array.
get photos(): FormArray {
    return this.roomForm.get('photos') as FormArray;
};

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

En composant html

<input type="file" class="custom-file-input form-control" id="files" multiple (change)="detectFiles($event)" accept="image/x-png,image/jpeg">

<div class="images-preview mt-2" *ngIf="photos.length">
    <div formArrayName="photos" *ngFor="let photo of photos.controls; let i = index;">
        <div [formGroupName]="i">
            <img [src]="photo.controls.url.value" class="card-img-top" alt="Image Preview">
        </div>
    </div>
</div>

Vous pouvez éviter le langage HTML si vous ne souhaitez pas afficher l'aperçu. Lors de la soumission du formulaire, vous obtiendrez des valeurs comme ci-dessous.

{
    text_input: "",
    photos: [
       {
           file: <File Object>,
           url: <Base64 String here>
       },
       {
           file: <File Object>,
           url: <Base64 String here>
       },
       ....
    ] 
}

J'espère que cela vous aidera et aidera également les autres peuples . Merci.