132

This is how my input tag looks like:

<input type="file" placeholder="File Name" name="filename" (change)="onChange($event)">
<button>Reset</button>

I want to reset the selected file in Angular 2. Help would be greatly appreciated. Let me know if you need more details.

P.S.

I could get file details from $event parameters and save it in a typescript variable, but this variable is not bound to the input tag.

Akash
  • 4,412
  • 4
  • 30
  • 48
  • When you say reset, what exactly do you mean. Can you create a http://plnkr.co/ and post what problem are you facing – abhinav Oct 20 '16 at 22:24

13 Answers13

284

You can use ViewChild to access the input in your component. First, you need to add #someValue to your input so you can read it in the component:

<input #myInput type="file" placeholder="File Name" name="filename" (change)="onChange($event)">

Then in your component you need to import ViewChild from @angular/core:

import { ViewChild } from '@angular/core';

Then you use ViewChild to access the input from template:

@ViewChild('myInput')
myInputVariable: ElementRef;

Now you can use myInputVariable to reset the selected file because it's a reference to input with #myInput, for example create method reset() that will be called on click event of your button:

reset() {
    console.log(this.myInputVariable.nativeElement.files);
    this.myInputVariable.nativeElement.value = "";
    console.log(this.myInputVariable.nativeElement.files);
}

First console.log will print the file you selected, second console.log will print an empty array because this.myInputVariable.nativeElement.value = ""; deletes selected file(s) from the input. We have to use this.myInputVariable.nativeElement.value = ""; to reset the value of the input because input's FileList attribute is readonly, so it is impossible to just remove item from array. Here's working Plunker.

Marco
  • 1,073
  • 9
  • 22
Stefan Svrkota
  • 48,787
  • 9
  • 98
  • 87
36

I typically reset my file input after capturing the selected files. No need to push a button, you have everything required in the $event object that you're passing to onChange:

onChange(event) {
  // Get your files
  const files: FileList = event.target.files;

  // Clear the input
  event.target.value = null;
}

Different workflow, but the OP doesn't mention pushing a button is a requirement.

*UPDATED 6/14/2021 to replace event.srcElement with event.target, now that srcElement has been deprecated

2Toad
  • 14,799
  • 7
  • 42
  • 42
28

Angular 5

html

<input type="file" #inputFile>

<button (click)="reset()">Reset</button>

template

@ViewChild('inputFile') myInputVariable: ElementRef;

reset() {
    this.myInputVariable.nativeElement.value = '';
}

Button is not required. You can reset it after change event, it is just for demonstration

Admir
  • 2,876
  • 1
  • 19
  • 19
16

One way to achieve it is to wrap your input in <form> tag and reset it.

I'm not considering attaching thr form to NgForm or FormControl either.

@Component({
  selector: 'form-component',
  template: `
    <form #form>
      <input type="file" placeholder="File Name" name="filename">
    </form>
    <button (click)="reset()">Reset</button>
`
})
class FormComponent {



  @ViewChild('form') form;


  reset() {
    this.form.nativeElement.reset()
  }
}

https://plnkr.co/edit/Ulqh2l093LV6GlQWKkUA?p=preview

Edmar Miyake
  • 12,047
  • 3
  • 37
  • 38
  • can we use `.reset()` method on viewChild ?? – Pardeep Jain Apr 07 '17 at 07:32
  • Hello Edmar ... can you help me out with the question on this link ...https://stackoverflow.com/questions/48769015/filter-in-the-dropdown-not-working-with-data-from-http-get-request – Heena Feb 13 '18 at 15:12
4

Short version Plunker:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
      <input #myInput type="file" placeholder="File Name" name="filename">
      <button (click)="myInput.value = ''">Reset</button>
  `
})
export class AppComponent {


}

And i think more common case is to not using button but do reset automatically. Angular Template statements support chaining expressions so Plunker:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
      <input #myInput type="file" (change)="onChange(myInput.value, $event); myInput.value = ''" placeholder="File Name" name="filename">
  `
})
export class AppComponent {

  onChange(files, event) {
    alert( files );
    alert( event.target.files[0].name );
  }

}

And interesting link about why there is no recursion on value change.

Oleg Mazko
  • 1,720
  • 15
  • 10
3

I think its simple, use #variable

<input #variable type="file" placeholder="File Name" name="filename" (change)="onChange($event); variable.value='' ">
<button>Reset</button>

"variable.value = null" option also available

Fawad Mukhtar
  • 780
  • 5
  • 9
3

you may use template reference variable and send to a method

html

<input #variable type="file" placeholder="File Name" name="filename" (change)="onChange($event, variable);">

component

onChange(event: any, element): void {
    // codes
    element.value = '';
  }
2

In my case I did it as below:

 <input #fileInput hidden (change)="uploadFile($event.target.files)" type="file" />
 <button mat-button color="warn" (click)="fileInput.value=''; fileInput.click()"> Upload File</button>

I am resetting it using #fileInput in HTML rather than creating a ViewChild in component.ts . Whenever the "Upload File" button is being clicked, first it resets the #fileInput and then triggers #fileInput.click() function. If any separate button needed to reset then on click #fileInput.value='' can be executed.

CodeAdocate
  • 149
  • 1
  • 4
1

I am using a a very simple aproach. After a file has been uploaded, i shortly remove the input control, using *ngIf. That will cause the input field being removed from the dom and re-added, consequencely it is a new control, and therefore it is emply:

showUploader: boolean = true;

async upload($event) {
  await dosomethingwiththefile();
  this.showUploader = false;
  setTimeout(() =>{ this.showUploader = true }, 100);
}
<input type="file" (change)="upload($event)" *ngIf="showUploader">
Kjeld Poulsen
  • 213
  • 3
  • 4
0

If you are facing issue with ng2-file-upload,

HTML:

<input type="file" name="myfile" ` **#activeFrameinputFile** `ng2FileSelect [uploader]="frameUploader" (change)="frameUploader.uploadAll()" />

component

import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';

@ViewChild('`**activeFrameinputFile**`') `**InputFrameVariable**`: ElementRef;

this.frameUploader.onSuccessItem = (item, response, status, headers) => {
    this.`**InputFrameVariable**`.nativeElement.value = '';
   };
Abhishek Ekaanth
  • 2,511
  • 2
  • 19
  • 40
0

template:

<input [(ngModel)]="componentField" type="file" (change)="fileChange($event)" placeholder="Upload file">

component:

fileChange(event) {
        alert(this.torrentFileValue);
        this.torrentFileValue = '';
    }
}
Hett
  • 3,484
  • 2
  • 34
  • 51
0

I have add this input tag into form tag..

 <form id="form_data">
  <input  type="file" id="file_data"  name="browse"
  (change)="handleFileInput($event, dataFile, f)"  />
</form>

I angular typescript, I have added below lines, get your form id in document forms and make that value as null.

    for(let i=0; i<document.forms.length;i++){
      if(document.forms[i].length > 0){
             if(document.forms[i][0]['value']){ //document.forms[i][0] = "file_data"
                 document.forms[i][0]['value'] = "";
              }
      }
    }

Print document.forms in console and you can get idea..

Deepa
  • 850
  • 1
  • 10
  • 11
-1
<input type="file" id="image_control" (change)="validateFile($event)" accept="image/gif, image/jpeg, image/png" />
validateFile(event: any): void {
    const self = this;
    if (event.target.files.length === 1) {
      event.srcElement.value = null;
    }
  }