20

I'm writing a component with a file picker that uploads a file to our CDN. I'm trying to add a reactive form on this component to validate the image input, so I can check against file name/extension etc, and keep it wrapped it in a form so I can keep the benefits of Angulars validation.

My component HTML is

<form class="mt-4" [formGroup]="form">
  <div class="form-group form-inline">
    <label class="btn btn-secondary btn-file">Browse
       <input name="file" type="file" (change)="onChange($event)" formControlName="imageInput"
    </label>

    <p *ngIf="file" class="pl-4 align-middle mb-0">{{file.name}}</p>
  </div>

  <button type="button" class="btn btn-primary">Upload</button>
</form>

And my component code behind is

onChange(event: EventTarget) {
  // file picker code

  this.form = this.formBuilder.group({
      imageInput: [this.file.name, CustomValidators.imageValidator]
  });
}

The CustomValidars.imageValidator only just logs the input at the minute.

When the component is loaded, the error message displays as 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.

Basically, I want to use the file input in my reactive form, so I can validate against the filename.

2

4 Answers 4

44

As @ibrahim mention it's not implemented yet, but i got the same problem and solved it using hidden field. on onFileChange method set file.name to hidden field, where you can validate.

   <form class="mt-4" [formGroup]="form">
      <div class="form-group form-inline">
        <label class="btn btn-secondary btn-file">Browse
           <input name="file" type="file" (change)="onFileChange($event)">
           <input type="hidden" name="fileHidden" formControlName="imageInput"/> <!-- Validation Field -->
        </label>

        <p *ngIf="file" class="pl-4 align-middle mb-0">{{file.name}}</p>
      </div>
      <button type="button" class="btn btn-primary">Upload</button>
    </form>



onFileChange($event) {
     let file = $event.target.files[0]; // <--- File Object for future use.
     this.form.controls['imageInput'].setValue(file ? file.name : ''); // <-- Set Value for Validation
}
fileName = '';
this.form = this.formBuilder.group({
      imageInput: [fileName, Validators.required]
});
Sign up to request clarification or add additional context in comments.

2 Comments

Nice solution (I also added the file file input as a control so that I could add validation messages)
no databinding solutions included with existing files.
4

The value of <input type="file"> is read-only, You need to set the option emitModelToViewChange:false when calling setValue() to avoid that error :

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.

SOLUTION :

this.form.get('<name>').setValue(file, {emitModelToViewChange: false});

1 Comment

Thanks @s4suryapal, even after 4 years this one is the code which saved me. thanks
3

export class myClass implements OnInit {

  myForm = new FormGroup({
    name: new FormControl(''),
    myFile: new FormControl('')
  })

  onFileChange($event) {

    this.myForm.patchValue({
      myFile: $event.target.files[0]
    })
  }

}
<input type="file" (change)="onFileChange($event)">

1 Comment

Add some context of answer.
-1

Remove formControlName="imageInput" from your <input type="file" and this will solve your problem.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.