使用angular 2 beta,我似乎无法让<input type="file">
工作。
使用诊断功能,我可以看到其他type
的双向绑定,例如text
。
<form>
{{diagnostic}}
<div class="form-group">
<label for="fileupload">Upload</label>
<input type="file" class="form-control" [(ngModel)]="model.fileupload">
</div>
</form>
在我的TypeScript文件中,我有以下诊断线:
get diagnostic() { return JSON.stringify(this.model); }
可能是不是JSON的问题吗?值为null
。
我无法真正验证input
的值。 У尽管“选择文件...”旁边的文字更新了,但由于某些原因我无法看到DOM的差异。
答案 0 :(得分:67)
我认为它不受支持。如果您查看此DefaultValueAccessor
指令(请参阅https://github.com/angular/angular/blob/master/modules/angular2/src/common/forms/directives/default_value_accessor.ts#L23)。您将看到用于更新绑定元素的值为$event.target.value
。
这不适用于类型为file
的输入,因为文件对象可以到达$event.srcElement.files
。
有关详细信息,您可以查看此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);
}
}
答案 1 :(得分:39)
@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() {
}
}
答案 2 :(得分:28)
访问附件有一种更好的方法。您可以使用template reference variable来获取输入元素的实例。
以下是基于第一个答案的示例:
@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);
}
}
这是一个example app来证明这一点。
模板引用变量可能很有用,例如您可以直接在控制器中通过@ViewChild访问它们。
答案 3 :(得分:5)
使用模板引用变量和ViewChild的另一种方法,如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);
}
}
答案 4 :(得分:2)
试试这个小型lib,适用于Angular 5.0.0
使用ng2-file-upload 1.3.0的快速入门示例:
用户点击自定义按钮,从隐藏的输入类型=“文件”触发上传对话框,选择单个文件后自动上传。
<强> 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 = "";
}
替代lib,适用于Angular 4.2.4,但需要采用一些变通方法来采用Angular 5.0.0
答案 5 :(得分:0)
如果您有一个包含多个文件和其他输入的复杂表单,那么这个解决方案可以与ngModel
一起使用。
它由一个文件输入组件组成,该组件包装一个简单的文件输入并实现ControlValueAccessor
接口,使其可由ngModel
使用。该组件将FileList
对象公开为ngModel
。
此解决方案基于this文章。
组件的使用方式如下:
<file-input name="file" inputId="file" [(ngModel)]="user.photo"></file-input>
<label for="file"> Select file </label>
这是组件代码:
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;
}
}
这是组件模板:
<input type="file" name="{{ name }}" id="{{ inputId }}" multiple="multiple" (change)="changeFile($event)"/>
答案 6 :(得分:0)
只需尝试(onclick)="this.value = null"
在您的html页面中,添加onclick方法以删除先前的值,以便用户可以再次选择相同的文件。