Search code examples
angularangular-reactive-formsangular-forms

Angular 7 : How do I submit file/image along with my reactive form?


I have created simple reactive form with text input and when form is being submitted I want to pass along image from file input. Every time I google I get tutorials, where they show me how I can upload file, but it is being done without other input field. I understand how to do that, what I don't understand how to submit both my form along with file input in one submission.

In my scenario, am I not supposed to user reactive forms and instead simple new FormData() and append every input into that?

If I can do that, leave me simple example.

edit: How to include a file upload control in an Angular2 reactive form? This is not answer. Answer market there is not posting file along with reactive form, it is posting file alone.


Solution

  • Had this issue too, what I did was to construct a FormData, the using a loop add the formGroup values to the form Data

    import {
      Component,
      OnInit,
      ChangeDetectorRef
    } from '@angular/core';
    import {
      FormGroup,
      FormBuilder,
      Validators
    } from '@angular/forms';
    
    
    export class TodoFormComponent {
      todoForm: FormGroup = this.fb.group({
        todo: ['', Validators.required],
        image: ['', Validators.required], //making the image required here
        done: [false]
      })
    
      constructor(
        private fb: FormBuilder,
        private cd: ChangeDetectorRef
      ) {}
    
      /**
       *@param event {EventObject} - the javascript change event
       *@param field {String} - the form field control name
       */
      onFileChange(event, field) {
        if (event.target.files && event.target.files.length) {
          const [file] = event.target.files;
          // just checking if it is an image, ignore if you want
          if (!file.type.startsWith('image')) {
            this.todoForm.get(field).setErrors({
              required: true
            });
            this.cd.markForCheck();
          } else {
            // unlike most tutorials, i am using the actual Blob/file object instead of the data-url
            this.todoForm.patchValue({
              [field]: file
            });
            // need to run CD since file load runs outside of zone
            this.cd.markForCheck();
          }
        }
    
        onSubmit() {
          const formData = new FormData();
          Object.entries(this.todoForm.value).forEach(
            ([key, value]: any[]) => {
              formData.set(key, value);
            }
    
            //submit the form using formData
            // if you are using nodejs use something like multer
          )
        }
    
      }
    <form [formGroup]="todoForm" (ngSubmit)="onSubmit()">
      <input type="file" formControlName="image" (onchange)="onFileChange($event, 'image')"/>
      <textarea formControlName="todo"></textarea>
      <button type="submit">Submit</button>
    </form>

    On the server side you can process the request as you would process form-data request