angular - 比较 2 个输入字段的值以通过模板验证 Angular 7 中的表单
问题描述
我在迁移到 Angular 7 的第一周,我一直在使用基于模板的基本验证在我的项目中做基本表单,但我现在需要基于一个字段的值必须高于其他
我已经尝试在组件控制器中使用这些值本身,但是虽然我能够确认这些值是否有效,但我无法使用此代码向用户显示问题所在
if (issueThresholdForm.value.lowScore > issueThresholdForm.value.highScore) {
// Show user error
// This is the messing part, I guess
}
这是我正在使用的模板
<div *ngIf="_issueCategory">
<form (submit)="submitIssueThreshold(issueThresholdForm)" #issueThresholdForm="ngForm">
<mat-form-field class="half-width" floatLabel="always">
<mat-label [translate]="'issueThreshold.modals.highScore'"></mat-label>
<input name="highScore" type="number" matInput placeholder="0" [(ngModel)]="_issueCategory.highScore"
required #highScore="ngModel">
</mat-form-field>
<mat-form-field class="half-width" floatLabel="always">
<mat-label [translate]="'issueThreshold.modals.lowScore'"></mat-label>
<input name="lowScore" type="number" matInput placeholder="0" [(ngModel)]="_issueCategory.lowScore"
required #lowScore="ngModel">
</mat-form-field>
<mat-form-field class="full-width" floatLabel="always">
<mat-label [translate]="'issueThreshold.modals.description'"></mat-label>
<textarea name="description" matInput [(ngModel)]="_issueCategory.thresholdDescription">
</textarea>
</mat-form-field>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" [translate]="'modal-confirm.cancel'"></button>
<button type="submit" class="btn btn-primary primary" [disabled]="issueThresholdForm.invalid || issueThresholdForm.pristine" [translate]="'modal-confirm.submit'"></button>
</div>
</form>
</div>
解决方案
编辑:
使用相同的解决方案以反应方式进行编辑。所以创建表单组并添加一个附加到表单组的自定义验证器:
_issueCategory = { lowScore: 1, highScore: 2 };
issueThresholdForm: FormGroup;
constructor(private fb: FormBuilder) {
this.issueThresholdForm = this.fb.group({
highScore: [this._issueCategory.highScore, [Validators.required]],
lowScore: [this._issueCategory.lowScore, [Validators.required]]
}, { validators: validateScore })
}
验证器功能:
export function validateScore(
control: AbstractControl
): ValidationErrors | null {
if (control && control.get("highScore") && control.get("lowScore")) {
const highscore = control.get("highScore").value;
const lowscore = control.get("lowScore").value;
return (lowscore > highscore) ? { scoreError: true } : null
}
return null;
}
然后您可以删除 ngModel (重要!),因为它们不应该与反应形式混合。您还可以删除required
表单的所有验证,因此最终输入看起来就像:
<input type="number" matInput placeholder="0" formControlName="lowScore">
原来的:
我强烈建议Reactive forms,一开始他们可能会感到困惑,但完全值得。您可以更好地控制表单,正如 Nithin Kumar Biliya 在评论中提到的那样,单元测试更容易。
话虽如此....
这是一个使用模板驱动表单的解决方案,因为这是您当前正在使用的。
您可以制作一个附加到表单标签的指令,并且在该指令内部有一个验证器来比较高分和低分的值并将错误附加到表单或返回null
(这在表单中被认为是有效的)。所以验证器看起来像这样:
import { Directive } from "@angular/core";
import {
AbstractControl,
NG_VALIDATORS,
Validator,
ValidationErrors
} from "@angular/forms";
@Directive({
selector: "[scoreValidation]",
providers: [
{
provide: NG_VALIDATORS,
useExisting: ScoreValidatorDirective,
multi: true
}
]
})
export class ScoreValidatorDirective implements Validator {
constructor() {}
// here control is the formgroup
validate(control: AbstractControl): ValidationErrors | null {
if (control && control.get("highScore") && control.get("lowScore")) {
// the form controls and their value
const highscore = control.get("highScore").value;
const lowscore = control.get("lowScore").value;
// not valid, return an error
if (lowscore > highscore) {
return { scoreError: true };
}
// valid
return null;
}
// form controls do not exist yet, return null
return null;
}
}
将指令添加到 appmodule 中的声明数组中,并通过将此指令附加到表单标签来使用它:
<form .... scoreValidation>
并且可以使用显示错误*ngIf="issueThresholdForm.hasError('scoreError')
推荐阅读
- java - Twitter4J Android 搜索查询返回 Null
- webserver - 如何将数据发送到 Racket 服务器?
- c++ - 如何在 C++ 中保留一定数量的小数位(而不是有效数字)?
- python - 迭代合并
- android - 如何通过单击按钮将使用 Recycler Firestore Adapter 显示的 Cloud Firestore 中的所有项目添加到另一个数据库
- java - 使用杰克逊数据绑定序列化对象时出现 Java InvalidDefinitionException
- command-line - 如何在 ImageMagick 中批量调整图像大小,同时保持纵横比和最大宽度和高度?
- mysql - 在nodejs和mysql中发送后无法设置标头
- java - 如何获得一个按钮来运行片段中的功能?
- javascript - 使用 foxit pdf 库突出显示 PDF 中的文本内容