0

Issue

I currently have a form that has a bunch of fields, one of them being a file upload field. They all form part of a FormGroup that is declared in my constructor. Now all the text controls I am able to access by using this.control.value except my file control. When I try to access the value of the form control for the file all I get is C:/fakepath/image.png.

Is there a way to access the actual file data so that I can upload it to my API?


Code

My FormControl declarations:

/**
 * Category of the product
 */
public category = new FormControl('', [
  Validators.required
]);

/**
 * Name of the product
 */
public name = new FormControl('', [
  Validators.required,
  Validators.minLength(3)
]);

/**
 * Description of the product
 */
public description = new FormControl('', [
  Validators.required
]);

/**
 * Price of the product
 */
public price = new FormControl('', [
  Validators.required
]);

/**
 * Image of the product
 */
public image = new FormControl('', [
  Validators.required
]);

My constructor for the page/component:

constructor(private api: ApiService,
  private formBuilder: FormBuilder) {

    this.productForm = formBuilder.group({
      category: this.category,
      name: this.name,
      description: this.description,
      price: this.price,
      image: this.image
    });
}

How I am currently trying to access the file

public async createProduct(): Promise<any> {
  console.log(this.image.value);
}
2
  • Angular doesn't support files in its forms. You will have to set it by hand (as far as I know, of course) Commented Mar 4, 2019 at 12:05
  • you can serialize this.productForm and add it into the FormData as a property and add the image as a seperate property. Commented Mar 4, 2019 at 12:06

2 Answers 2

3

Step 1: HTML Template (file-upload.component.html)

Define simple input tag of type file. Add a function to (change)-event for handling choosing files.

<div class="form-group">
    <label for="file">Choose File</label>
    <input type="file"
           id="file"
           (change)="handleFileInput($event.target.files)">
</div>

Step 2: Upload Handling in TypeScript (in component file)

Define an default variable for selected file.

fileToUpload: File = null;

Create function which you use in (change)-event of your file input tag:

handleFileInput(files: FileList) {
    this.fileToUpload = files.item(0);
}

Step 3: File-Upload Service

By uploading a file via POST-method you should use FormData, because so you can add file to http request.

postFile(fileToUpload: File): Observable<boolean> {
    const endpoint = 'your-destination-url';
    const formData: FormData = new FormData();
    // Append image file to formdata as a seperate property
    formData.append('fileKey', fileToUpload, fileToUpload.name);

    // Append reactive form data too in a seperate property
    formData.append('productForm', JSON.stringify(this.productForm, null, 4));
    return this.httpClient
      .post(endpoint, formData, { headers: yourHeadersConfig })
      .map(() => { return true; })
      .catch((e) => this.handleError(e));
}
Sign up to request clarification or add additional context in comments.

Comments

0

Is there a way to access the actual file data so that I can upload it to my API?

You can access it in that way:

// template
<input
 type="file" (change)="onFileChanged($event)"
>

// component
onFileChanged(event) {
  // this.image will be updated each time the file
  // in input will be changed
  this.image = event.target.files[0];
  console.log(this.image);
}


createProduct(): Promise<Product> {
  console.log(this.image);
  const formData = new FormData();
  formData.append(
    'image',
    this.image
  );

  // add other fields to formData:
  formData.append("name", this.productForm.controls['name'].value);

  formData.append("description", this.productForm.controls['description'].value);

  const url = 'urlToApi';

  return this.http.post(url, formData)
    .toPromise()
    .then(response => {
      return response;
    })
    .catch(err => console.log(err));
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.