Angular 2似乎在文件输入更改时运行验证时遇到麻烦。
我插了一下来说明这个问题:
我创建了一个像
这样的formGroupthis.frm = new FormGroup({
file: new FormControl("", this.validateFile)
});
在validateFile函数中,我抛出一个警报并记录到控制台:
public validateFile(formControl: FormControl): {[key: string]: any; } {
alert('Validation ran');
console.log('Validation ran');
}
用于说明问题的Plunkr:https://plnkr.co/edit/Pgcg4IkejgaH5YgbY3Ar?p=preview
验证将在初始化页面时运行,但每次更改要上载的文件时都不会运行。
这个问题有解决办法吗?
答案 0 :(得分:36)
我使用kemsky的回答和Sebastien的评论来修复它。 我创建了一个ngValueAccessor,它在每个带有类型文件的输入上注册自己。
可以找到Plunkr here。
最相关的代码+解释如下:
这为文件输入添加了一个ControlValueAccessor,它有一天可能是角度框架本身的一部分(#7341)。 文件输入与其他控件的工作方式不同。这段代码确保将所选文件读取为值:
import {Directive} from "@angular/core";
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from "@angular/forms";
@Directive({
selector: "input[type=file]",
host : {
"(change)" : "onChange($event.target.files)",
"(blur)": "onTouched()"
},
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: FileValueAccessor, multi: true }
]
})
export class FileValueAccessor implements ControlValueAccessor {
value: any;
onChange = (_) => {};
onTouched = () => {};
writeValue(value) {}
registerOnChange(fn: any) { this.onChange = fn; }
registerOnTouched(fn: any) { this.onTouched = fn; }
}
对于' required'验证我通过将静态验证方法添加到文件FormControl for ReactiveForms来使用验证器。 (或作为模板驱动表格的指令)。
import {Directive} from "@angular/core";
import {NG_VALIDATORS, Validator, FormControl} from "@angular/forms";
@Directive({
selector: "[requiredFile]",
providers: [
{ provide: NG_VALIDATORS, useExisting: FileValidator, multi: true },
]
})
export class FileValidator implements Validator {
static validate(c: FormControl): {[key: string]: any} {
return c.value == null || c.value.length == 0 ? { "required" : true} : null;
}
validate(c: FormControl): {[key: string]: any} {
return FileValidator.validate(c);
}
}
构建我的表单如下所示:
private buildForm() {
this.frm = new FormGroup({
file: new FormControl("", [FileValidator.validate])
});
}
对于html:
<input type="file" formControlName="file"/>
答案 1 :(得分:8)
Angular 4+改变了主机绑定。
import { Directive, HostListener } from "@angular/core";
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from "@angular/forms";
@Directive({
selector: "input[type=file]",
providers: [
{provide: NG_VALUE_ACCESSOR, useExisting: FileValueAccessorDirective, multi: true}
]
})
export class FileValueAccessorDirective implements ControlValueAccessor {
@HostListener('change', ['$event.target.files']) onChange = (_) => {};
@HostListener('blur') onTouched = () => {};
writeValue(value) {}
registerOnChange(fn: any) { this.onChange = fn; }
registerOnTouched(fn: any) { this.onTouched = fn; }
}
答案 2 :(得分:2)
目前不支持file
类型的输入,请参阅#7341