[英]Compare the values of 2 input fields to validate the form in Angular 7 through the template
我在遷移到 Angular 7 的第一周,我一直在使用基於模板的基本驗證在我的項目中做基本的 forms,但我現在需要基於一個字段的值必須高於其他
我已經嘗試在組件 controller 中使用這些值本身,但是雖然我能夠確認這些值是否有效,但我無法使用此代碼向用戶顯示問題所在
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 })
}
驗證器 function:
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')
顯示錯誤
我強烈推薦反應式 forms,但如果你想這樣做,你可以:
將以下p tag
放在 lowScore 輸入下:
<p class="text-danger" [hidden]="(lowerScore.value > higerScore.value ? false: true) || (lowScore.pristine && !issueThresholdForm.submitted)">
The lower scrore can not be greater than higer score
</p>
您可以在Reactive Forms
中使用Custom Validations
,如下所示。
HTML
<div>
<form [formGroup]="myForm">
<label>Low Score: </label>
<input formControlName="lowScore" type="number">
<br/><br/>
<label>High Score: </label>
<input formControlName="highScore" type="number">
<div>
<span style="color: red" *ngIf="myForm.get('highScore').touched && myForm.get('highScore').hasError('higherThan')">High score should be higher than lower score.</span>
</div>
</form>
</div>
TS
export class AppComponent {
myForm: FormGroup;
constructor() {
this.myForm = new FormGroup({
highScore: new FormControl(0, [this.lowerThan('lowScore')]),
lowScore: new FormControl(0, null)
});
}
lowerThan(field_name): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
const input = control.value;
const isLower = control.root.value[field_name] >= input;
return isLower ? {'lowerThan': {isLower}}: null;
};
}
}
在這里找到工作StackBlitz 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.