我有自定义图片上传验证程序。此验证器确保mime类型正确,检查文件大小,并确保尺寸正确。此验证器的一部分创建一个图像元素,并为其提供datauri(作为src)来检查宽度/高度。由于上次检查,它使用img.onload
事件,因此,这是一个异步验证器。
我的验证员将接受网址和数据uris。
以下是我的验证人的来源。我创建了一个FileValidator
基类,用于检查mimeType和文件大小,ImageValidator
检查维度。
验证类如下。 我创建了这些类,因为它们需要给出ValidationRules的状态。验证器方法是actor
FileValidator
export class FileValidator {
constructor(protected _rules: FileValidationRules) {}
public validator(control: FormControl): Promise<any> {
return new Promise((resolve, reject) => {
var value = control.value;
if (value) {
if (this.isDataUri(value)) {
if (this._rules.acceptedMimeTypes && this._rules.acceptedMimeTypes.length) {
var mimeType = this.getMimeType(value);
var allowedMimeType = false;
for (var i = 0; i < this._rules.acceptedMimeTypes.length; i++) {
if (this._rules.acceptedMimeTypes[i] === mimeType) {
allowedMimeType = true;
break;
}
}
if (!allowedMimeType) {
resolve({
fileValidator: `File type not allowed: ${mimeType}. Allowed Types: ${this._rules.acceptedMimeTypes}`
});
}
if (this._rules.maxSize) {
var blob = this.dataURItoBlob(value);
blob.size > this._rules.maxSize;
resolve({
fileValidator: `File is too large. File Size: ${this.getFriendlyFileSize(blob.size)}, Max Size: ${this.getFriendlyFileSize(this._rules.maxSize)}`
});
}
}
} else if (!this.isUrl(value)) {
resolve({
fileValidator: 'Unknown format'
});
}
}
resolve();
});
}
... Helper Methods
}
ImageValidator
export class ImageValidator extends FileValidator {
constructor(_rules: ImageValidationRules) {
super(_rules);
}
public validator(control: FormControl): Promise<any> {
return new Promise((resolve, reject) => {
super.validator(control).then((results) => {
if (results && results.fileValidator) {
resolve({
imageValidator: results.fileValidator
});
}
var value = control.value;
if (value) {
var rules = <ImageValidationRules>this._rules;
if (this.isDataUri(value)) {
if (rules.width || rules.height) {
var img: HTMLImageElement = document.createElement('img');
img.onload = () => {
var validSize = true;
if (rules.width && img.width !== rules.width) {
validSize = false;
}
if (rules.height && img.height !== rules.height) {
validSize = false;
}
if (!validSize) {
resolve({
imageValidator: `Image must be ${rules.width || 'any'}x${rules.height || 'any'}. Actual Size: ${img.width}x${img.height}`
});
}
};
img.src = value;
}
}
}
resolve();
});
});
}
}
这一切都有效。如果我选择的图像不符合要求,我会得到正确的错误信息。
但是这个图片上传器位于标签区域。
如果我在标签之间循环,我会收到此错误 -
错误:检查后表达式已更改。以前的价值:&#39; true&#39;。当前价值:&#39; false&#39;。
简单地说,我的选项卡区域标记是 -
<li *ngFor="let page of pages"
[ngClass]="{active: page === activePage}">
<a (click)="setActivatePage(page)">
<i *ngIf="getFormGroup(page).invalid" class="fa fa-exclamation-circle font-red"></i>
{{page.title}}
</a>
</li>
我的标签内容(简称) -
<element *ngFor="let input of activePage.inputs"
... etc>
</element>
这一行 -
<i *ngIf="getFormGroup(page).invalid" class="fa fa-exclamation-circle font-red"></i>
导致错误。但我无法弄清楚原因。我认为这与我使用异步验证器这一事实有关。
如果我在我的异步验证器中注释掉所有resolve
个调用,它运行正常(但显然我的验证停止了)。
因此,根据我可以收集的内容,更改活动页面会重新应用验证程序。并且异步验证器在检查有效性后更新有效性。并且对于某种原因这对于角度来说是一个问题,就像它没有考虑异步任务将异步更新状态。
有谁知道这可能是什么。对不起,我无法提供简化的工作示例,我的系统很复杂。
修改
此外,仅在设置了输入值时才会出现。如果我在控件上调用reset或将值设置为null(在验证器中),则在循环选项卡时不会发生这种情况。
答案 0 :(得分:1)
答案是,当没有任何改变时我正在解析验证器 -
resolve();
我认为无论如何都应该解决异步验证器。但事实似乎并非如此。删除此空解决方案可以解决问题。