Loading file from <input type = "file">
Using angular 2 beta, I cannot get <input type="file"> .
Using diagnostics, I see two-way binding for another type such as text .
<form> {{diagnostic}} <div class="form-group"> <label for="fileupload">Upload</label> <input type="file" class="form-control" [(ngModel)]="model.fileupload"> </div> </form> In my TypeScript file, I have the following diagnostic line:
get diagnostic() { return JSON.stringify(this.model); } Could it be that the problem is not being JSON? The value is null .
I can not really check the value of input . Despite the fact that the text next to "Select file ..." is being updated, for some reason I do not see the differences in the DOM.
I think it is not supported. If you look at this DefaultValueAccessor directive (see https://github.com/angular/angular/blob/master/modules/angular2/src/common/forms/directives/default_value_accessor.ts#L23 ). You will see that the value used to update the related item is $event.target.value .
This does not apply to an input of type file , since the file object can be reached $event.srcElement.files .
For more information, you can look at this plunkr: https://plnkr.co/edit/ozZqbxIorjQW15BrDFrg?p=info :
@Component({ selector: 'my-app', template: ` <div> <input type="file" (change)="onChange($event)"/> </div> `, providers: [ UploadService ] }) export class AppComponent { onChange(event) { var files = event.srcElement.files; console.log(files); } } 
@Component({ selector: 'my-app', template: ` <div> <input name="file" type="file" (change)="onChange($event)"/> </div> `, providers: [ UploadService ] }) export class AppComponent { file: File; onChange(event: EventTarget) { let eventObj: MSInputMethodContext = <MSInputMethodContext> event; let target: HTMLInputElement = <HTMLInputElement> eventObj.target; let files: FileList = target.files; this.file = files[0]; console.log(this.file); } doAnythingWithFile() { } } There is a slightly better way to access attached files. You can use the template reference variable to get an instance of the input element.
Here is an example based on the first answer:
@Component({ selector: 'my-app', template: ` <div> <input type="file" #file (change)="onChange(file.files)"/> </div> `, providers: [ UploadService ] }) export class AppComponent { onChange(files) { console.log(files); } } Here is an example application to demonstrate this in action.
Reference template variables may be useful, for example. you can access them via @ViewChild directly in the controller.
Another way to use the template reference variable and ViewChild suggested by Frelseren:
import { ViewChild } from '@angular/core'; @Component({ selector: 'my-app', template: ` <div> <input type="file" #fileInput/> </div> ` }) export class AppComponent { @ViewChild("fileInput") fileInputVariable: any; randomMethod() { const files = this.fileInputVariable.nativeElement.files; console.log(files); } } Also see https://stackoverflow.com/a/312977/
Try this small library, it works with Angular 5.0.0
Quick start example with ng2-file-upload 1.3.0:
The user clicks the user button, which launches the download dialog from the hidden input type = "file", the download starts automatically after selecting one file.
app.module.ts:
import {FileUploadModule} from "ng2-file-upload"; your.component.html:
... <button mat-button onclick="document.getElementById('myFileInputField').click()" > Select and upload file </button> <input type="file" id="myFileInputField" ng2FileSelect [uploader]="uploader" style="display:none"> ... your.component.ts:
import {FileUploader} from 'ng2-file-upload'; ... uploader: FileUploader; ... constructor() { this.uploader = new FileUploader({url: "/your-api/some-endpoint"}); this.uploader.onErrorItem = item => { console.error("Failed to upload"); this.clearUploadField(); }; this.uploader.onCompleteItem = (item, response) => { console.info("Successfully uploaded"); this.clearUploadField(); // (Optional) Parsing of response let responseObject = JSON.parse(response) as MyCustomClass; }; // Asks uploader to start upload file automatically after selecting file this.uploader.onAfterAddingFile = fileItem => this.uploader.uploadAll(); } private clearUploadField(): void { (<HTMLInputElement>window.document.getElementById('myFileInputField')) .value = ""; } An alternative lib that works in Angular 4.2.4, but requires some workarounds to make Angular 5.0.0
If you have a complex form with several files and other data, here is a solution that works well with ngModel .
It consists of a file input component that wraps a simple file input and implements the ControlValueAccessor interface to make it ngModel . The component provides a FileList object to an FileList object.
This decision is based on this article.
The component is used like this:
<file-input name="file" inputId="file" [(ngModel)]="user.photo"></file-input> <label for="file"> Select file </label> Here is the component code:
import { Component, Input, forwardRef } from '@angular/core'; import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; const noop = () => { }; export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => FileInputComponent), multi: true }; @Component({ selector: 'file-input', templateUrl: './file-input.component.html', providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR] }) export class FileInputComponent { @Input() public name:string; @Input() public inputId:string; private innerValue:any; constructor() { } get value(): FileList { return this.innerValue; }; private onTouchedCallback: () => void = noop; private onChangeCallback: (_: FileList) => void = noop; set value(v: FileList) { if (v !== this.innerValue) { this.innerValue = v; this.onChangeCallback(v); } } onBlur() { this.onTouchedCallback(); } writeValue(value: FileList) { if (value !== this.innerValue) { this.innerValue = value; } } registerOnChange(fn: any) { this.onChangeCallback = fn; } registerOnTouched(fn: any) { this.onTouchedCallback = fn; } changeFile(event) { this.value = event.target.files; } } And here is the component template:
<input type="file" name="{{ name }}" id="{{ inputId }}" multiple="multiple" (change)="changeFile($event)"/> just try (onclick)="this.value = null"
on the html page, add the onclick method to remove the previous value so that the user can select the same file again.