1

Is it possible to send a file with reactive forms(model driven)? Files are from formData and another data is from FormGroup, how to combine this and send to nodejs?

Take file from:

<input formControlName="name" class="form-control" type="text">
<input formControlName="surname" class="form-control" type="text">
<input formControlName="email" class="form-control" type="mail">
<input type="file"(change)="addPhoto($event)" />

Create FormControl and FormGroup

createFormControls() {
  this.name = new FormControl("", Validators.required);
  this.surname = new FormControl("", Validators.required);
  this.email = new FormControl();
  this.file = new FormControl("");
}

createForm() {
  this.userData = new FormGroup({
    name: this.name,
    surname: this.surname,
    email: this.email,
    file: this.file
  });
}

push data

addPhoto(event) {
let target = event.target || event.srcElement;
this.files.push(target.files);
}

send data to node js

onSubmit() {
  if (this.userData.valid) {
  let filelist: FileList = this.files;
  const formData = new FormData();
  for (let i = 0; i < filelist.length; i++) {
    this.readyFile = filelist[i];
    formData.append('file', this.readyFile[0]);
  }
   // Here I have a main problem - there are "formData" and 
   // "this.userData.value" how send it to together(concat) ?

    this.apiService.updateUserData(--?--)
  }
}
andrzej
  • 495
  • 1
  • 7
  • 18

4 Answers4

0

inside addPhoto, replace with below code.

addPhoto(event) {
  let reader = new FileReader();

  if(event.target.files && event.target.files.length) {
    const [file] = event.target.files;
    reader.readAsDataURL(file);

    reader.onload = () => {
      this.formGroup.patchValue({
        file: reader.result
      });

      // need to run CD since file load runs outside of zone
      this.cd.markForCheck();
    };
  }
}
Suresh Kumar Ariya
  • 9,516
  • 1
  • 18
  • 27
  • If I clear understand, in this case files will be send not as files only as data and save to database. This is not the best solution for me. – andrzej Oct 16 '18 at 08:42
0

In your pushdata, change

this.userData('file').setValue(this.readyFile)

to

this.userData.get('file').setValue(this.readyFile)

and you can get more reference from this file upload in angular

Suryan
  • 701
  • 7
  • 17
  • This doesn't change anything. Your link describe about template driven, this work ok, but I need model driven approach. – andrzej Oct 16 '18 at 08:44
0

It's been a long time since your question has been asked but I think this could help you (or anybody that comes on this question)

public toFormData<T>( formValue: T ) {
  const formData = new FormData();

  for ( const key of Object.keys(formValue) ) {
  const value = formValue[key];
  formData.append(key, value);
  }

  return formData;
}

onSubmit() {
  if (this.userData.valid) {
    let filelist: FileList = this.files;
    const formData = this.toFormData(this.userData)
    for (let i = 0; i < filelist.length; i++) {
      this.readyFile = filelist[i];
      formData.append('file[]', this.readyFile[0]);
    }
    this.apiService.updateUserData(formData)
  }
}

First, you get your form as FormData, then you add to that FormData every file in your array (don't forget the "[]" to upload multiple files)

lvrnls
  • 13
  • 3
0

You can do a new formData.append() for each FormControl you want to send.

formData.append('name', this.name.value)
formData.append('surname', this.surname.value)
formData.append('email', this.email.value)
formData.append('file', this.file.value)

Im not really satisfied with this solution but this is the only solution i found. Hope it can help !