Using angular 2 beta, I cannot get . Using diagnostics, I see two-way binding for an...">

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.

+57
input angular file-upload
Feb 15 '16 at 0:07
source share
7 answers

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); } } 
+65
Feb 15 '16 at 8:33
source share
— -
 @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() { } } 
+38
Jan 04 '17 at 13:50
source share

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.

+26
Jun 05 '17 at 14:12
source share

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/

+5
Dec 12 '17 at 15:20
source share

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

+2
Nov 13 '17 at 12:41
source share

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)"/> 
0
May 09 '18 at 14:33
source share

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.

0
Feb 19 '19 at 7:15
source share



All Articles