Search code examples
htmlangularformsinputangular5

Angular 5 file upload: Failed to set the 'value' property on 'HTMLInputElement'


I have a form for uploading a file in an angular 5 app, and as I have copied it exactly from a code I had written a while ago, I can swear it had worked before.

Here is my HTML code:

<form [formGroup]="form" (ngSubmit)="onSubmit()">
        <div class="form-group">
            <label>File:</label>
            <input #theFile type="file" (change)="onFileChange($event)" accept=".png" class="form-control" 
                    formControlName="content" />
            <input type="hidden" name="fileHidden" formControlName="imageInput"/>

                    <!-- [(ngModel)]="model.content" -->
            
            <div class="alert alert-danger" *ngIf="!form.prestine && form.controls.content.errors?.noFile">
                Please provide a photo.
            </div>
            <div class="alert alert-danger" *ngIf="form.controls.content.errors?.fileTooBig">
                The file is too big and won't uploaded. Maximum allowed size is 500kb.
            </div>
        </div>
        <div class="form-group">
            <label>Notes</label>
            <textarea type="text" class="form-control" formControlName="notes" [(ngModel)]="model.notes" > </textarea>
        </div>
        <button type="submit" class="btn btn-primary" [disabled]="!form.valid">Submit</button>
        <button class="btn btn-default" type="button" (click)="close(false);">Cancel</button>
    </form>

Here is the "onFileChange" method used in the fileUpload control:

onFileChange($event)
  {
    if ($event.target.files.length > 0)
    {
        let ftu: File = null;
        ftu = $event.target.files[0];
        this.form.controls['content'].setValue(ftu);
        this.model.content = $event.target.files[0];
    }
  }

and here is the code for the custom validator I have written and used:

import { FormControl } from '@angular/forms';

export class SekaniRootImageValidators
{
    static sizeTooBig(control: FormControl)
    {
        if (!control.value)
        {
            return { noFile : true }
        }
        else  if (control.value[0].size > 505000)
        {
            return { fileTooBig: true}
        }
        return null;

    }
}

Now the issue is as soon as I select a file in the input control, I get this error message in the console:

ERROR DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.

This code has worked before, so I have no idea where to even start. Any help is appreciated!

ATTENTION: Here is a link to a working answer: Angular2: validation for <input type="file"/> won't trigger when changing the file to upload


Solution

  • Like the error is saying, you can only set an empty string to a file input value to clear the selection. It could open security risks otherwise. I can't imagine how that code could've ever worked. Maybe in some non-standard (bad) browser?

    Shouldn't that code work if you just remove the line, why do you need to set the same value to the input that it already has anyway?

    Edit: seems a custom ValueAccessor is needed for validating file inputs. Solution in another answer: Angular2: validation for <input type="file"/> won't trigger when changing the file to upload