如何使用 Angular5 检查表单控件的变化
How to check for changes in form controls using Angular5
我正在使用响应式表单,我有多个输入,我想为三个输入显示一个错误,验证是;字段是必需的,不应输入空格。
component.html:
<form [formGroup]="contratoForm" class="campo-form">
<div class="campoFormulario">
<label class="etiquetaFormulario" for="txtCodigoContrato">Código contrato</label>
<div style="display:inline-block; position: relative;" class="control">
<input [formControl]="txtCodigoContrato" type="text" id="txtCodigoContrato" name="txtCodigoContrato" class="cajaTexto ancho80" />
<span>/</span>
</div>
<div style="display:inline-block; position: relative;" class="control">
<input [formControl]="txtCodigoContrato2" type="text" id="txtCodigoContrato2" name="txtCodigoContrato2" class="cajaTexto ancho80" />
</div>
</div>
<div class="campoFormulario">
<label class="etiquetaFormulario" for="txtContrato">Contrato</label>
<div style="display:inline-block; position: relative;" class="control">
<input [formControl]="txtContrato" type="text" id="txtContrato" name="txtContrato" class="cajaTexto ancho350" />
</div>
</div>
<div *ngIf="((!txtCodigoContrato.valid && (txtCodigoContrato.dirty || txtCodigoContrato.touched)) && (txtCodigoContrato.hasError('required') || txtCodigoContrato.hasError('hasWhites')))
||
((!txtCodigoContrato2.valid && (txtCodigoContrato2.dirty || txtCodigoContrato2.touched)) && (txtCodigoContrato2.hasError('required') || txtCodigoContrato2.hasError('hasWhites')))
||
((!txtContrato.valid && (txtContrato.dirty || txtContrato.touched)) && (txtContrato.hasError('required') || txtContrato.hasError('hasWhites')))
">
<span>check the fields in red, they are required</span>
</div>
<div class="buttons">
<button class="btn btn-primary boton" type="button" style="float:right;" (click)="onCloseLink()">
<span class="glyphicon glyphicon-off"></span> Cancel
</button>
<button class="btn btn-primary boton" type="button" style="float:right;" (click)="limpiar()">
<span class="glyphicon glyphicon-trash"></span> Clean
</button>
<button type="submit" [disabled]="!contratoForm.valid" class="btn btn-primary boton" style="float:right;" (click)="onClick()">
<span class="glyphicon glyphicon-floppy-disk"></span> Save
</button>
</div>
</form>
component.ts:
import { Component, HostBinding, OnDestroy, OnInit, Input, Output, EventEmitter, ElementRef, NgModule, ViewChild, ChangeDetectorRef } from '@angular/core';
import { Validators, FormBuilder, FormControl, FormGroup, AbstractControl} from '@angular/forms';
import { AfterViewChecked } from '@angular/core/src/metadata/lifecycle_hooks';
@Component({
selector: 'app-formulario-contrato',
templateUrl: './contrato.component.html',
styleUrls: ['./contrato.component.css']
})
export class FormularioContratoComponent {
contratoForm: FormGroup;
constructor(private elRef: ElementRef, private formBuilder: FormBuilder, private cdRef: ChangeDetectorRef) {
this.createForm();
}
txtCodigoContrato = new FormControl('', [
Validators.required
,this.hasNotWhites
]);
txtCodigoContrato2 = new FormControl('', [
Validators.required
, this.hasNotWhites
]);
txtContrato = new FormControl('', [
Validators.required
, this.hasNotWhites
]);
createForm() {
this.contratoForm = this.formBuilder.group({
txtCodigoContrato: this.txtCodigoContrato
,txtCodigoContrato2: this.txtCodigoContrato2
,txtContrato: this.txtContrato
});
}
hasNotWhites(fieldControl: FormControl) {
if (fieldControl.value.trim() != '') {
return null
}
else {
return { hasWhites: true };
}
}
ngAfterViewChecked() {
this.cdRef.detectChanges();
}
limpiar() {
}
onClick() {
return null;
}
component.css:
/* some stuff...*/
:host /deep/ .control input.ng-invalid.ng-touched {
border-color: #ff8080;
}
验证工作正常,也就是说,当字段为空或输入空格时,它们会跳转。我的问题是我必须添加更多的表单控件,如果它包含消息可能会变得难以辨认:
<div *ngIf="((!txtCodigoContrato.valid && (txtCodigoContrato.dirty ||
txtCodigoContrato.touched)) && (txtCodigoContrato.hasError('required') ||
txtCodigoContrato.hasError('hasWhites')))
||
((!txtCodigoContrato2.valid && (txtCodigoContrato2.dirty ||
txtCodigoContrato2.touched)) && (txtCodigoContrato2.hasError('required') ||
txtCodigoContrato2.hasError('hasWhites')))
||
((!txtContrato.valid && (txtContrato.dirty || txtContrato.touched))
&& (txtContrato.hasError('required') || txtContrato.hasError('hasWhites')))
">
有没有什么方法可以通过打字稿来控制这些值,也就是说,每次控件中的值发生变化时,它都由打字稿中的一个函数控制,该函数 returns true or false 如果只要求该功能在我的 div 中的价值?
你可以这样做
this.contratoForm.valueChanges.subscribe(value = > //do something)
如果你愿意,你可以在之前添加一个映射函数,以从你关心的正在变化的表单中获取值
this.contratoForm.valueChanges
.map(values => values.txtCodigoContrato)
.subscribe(txtCodigoContrato = > //do something)
尝试将 valueChanges
与 Array.some()
函数一起使用
hasError: boolean = false;
constructor(private elRef: ElementRef,
private formBuilder: FormBuilder,
private cdRef: ChangeDetectorRef) {
this.createForm();
// listen to all changes on the form
this.contratoForm.valueChanges.subscribe(_ => {
const controllersToCheck = [
'txtCodigoContrato',
'txtCodigoContrato2',
'txtContrato'
];
this.hasError = controllersToCheck.some(ctrlName => {
let ctrl = this.contratoForm.get(ctrlName);
return (ctrl.dirty || ctrl.touched) &&
(ctrl.hasError('required') || ctrl.hasError('hasWhites'));
});
});
}
(检查!ctrl.valid
是多余的,因为如果控制器有错误,那么它是无效的)
HTML:
<div *ngIf="hasError">
<span>check the fields in red, they are required</span>
</div>
更新
如前所述 here
You can also listen to
{@link AbstractControl#statusChanges statusChanges} to be notified when the validation status is
re-calculated.
我认为它更适合你的情况,所以尝试订阅 statusChanges
事件(而不是 valueChanges
):
this.contratoForm.statusChanges.subscribe( ..........
更新 2
在您的 HTML:
中使用函数
<div *ngIf="hasErrors()">
<span>check the fields in red, they are required</span>
</div>
将此函数添加到您的组件 ts 文件中:
hasErrors() {
const controllersToCheck = [
'txtCodigoContrato',
'txtCodigoContrato2',
'txtContrato'
];
return controllersToCheck.some(ctrlName => {
let ctrl = this.contratoForm.get(ctrlName);
return (ctrl.dirty || ctrl.touched) &&
(ctrl.hasError('required') || ctrl.hasError('hasWhites'));
});
}
我创建了一个STACKBLITZ
如果您添加具有相同验证逻辑的新控制器,只需将它们的控件名称添加到 controllersToCheck
数组
我正在使用响应式表单,我有多个输入,我想为三个输入显示一个错误,验证是;字段是必需的,不应输入空格。
component.html:
<form [formGroup]="contratoForm" class="campo-form">
<div class="campoFormulario">
<label class="etiquetaFormulario" for="txtCodigoContrato">Código contrato</label>
<div style="display:inline-block; position: relative;" class="control">
<input [formControl]="txtCodigoContrato" type="text" id="txtCodigoContrato" name="txtCodigoContrato" class="cajaTexto ancho80" />
<span>/</span>
</div>
<div style="display:inline-block; position: relative;" class="control">
<input [formControl]="txtCodigoContrato2" type="text" id="txtCodigoContrato2" name="txtCodigoContrato2" class="cajaTexto ancho80" />
</div>
</div>
<div class="campoFormulario">
<label class="etiquetaFormulario" for="txtContrato">Contrato</label>
<div style="display:inline-block; position: relative;" class="control">
<input [formControl]="txtContrato" type="text" id="txtContrato" name="txtContrato" class="cajaTexto ancho350" />
</div>
</div>
<div *ngIf="((!txtCodigoContrato.valid && (txtCodigoContrato.dirty || txtCodigoContrato.touched)) && (txtCodigoContrato.hasError('required') || txtCodigoContrato.hasError('hasWhites')))
||
((!txtCodigoContrato2.valid && (txtCodigoContrato2.dirty || txtCodigoContrato2.touched)) && (txtCodigoContrato2.hasError('required') || txtCodigoContrato2.hasError('hasWhites')))
||
((!txtContrato.valid && (txtContrato.dirty || txtContrato.touched)) && (txtContrato.hasError('required') || txtContrato.hasError('hasWhites')))
">
<span>check the fields in red, they are required</span>
</div>
<div class="buttons">
<button class="btn btn-primary boton" type="button" style="float:right;" (click)="onCloseLink()">
<span class="glyphicon glyphicon-off"></span> Cancel
</button>
<button class="btn btn-primary boton" type="button" style="float:right;" (click)="limpiar()">
<span class="glyphicon glyphicon-trash"></span> Clean
</button>
<button type="submit" [disabled]="!contratoForm.valid" class="btn btn-primary boton" style="float:right;" (click)="onClick()">
<span class="glyphicon glyphicon-floppy-disk"></span> Save
</button>
</div>
</form>
component.ts:
import { Component, HostBinding, OnDestroy, OnInit, Input, Output, EventEmitter, ElementRef, NgModule, ViewChild, ChangeDetectorRef } from '@angular/core';
import { Validators, FormBuilder, FormControl, FormGroup, AbstractControl} from '@angular/forms';
import { AfterViewChecked } from '@angular/core/src/metadata/lifecycle_hooks';
@Component({
selector: 'app-formulario-contrato',
templateUrl: './contrato.component.html',
styleUrls: ['./contrato.component.css']
})
export class FormularioContratoComponent {
contratoForm: FormGroup;
constructor(private elRef: ElementRef, private formBuilder: FormBuilder, private cdRef: ChangeDetectorRef) {
this.createForm();
}
txtCodigoContrato = new FormControl('', [
Validators.required
,this.hasNotWhites
]);
txtCodigoContrato2 = new FormControl('', [
Validators.required
, this.hasNotWhites
]);
txtContrato = new FormControl('', [
Validators.required
, this.hasNotWhites
]);
createForm() {
this.contratoForm = this.formBuilder.group({
txtCodigoContrato: this.txtCodigoContrato
,txtCodigoContrato2: this.txtCodigoContrato2
,txtContrato: this.txtContrato
});
}
hasNotWhites(fieldControl: FormControl) {
if (fieldControl.value.trim() != '') {
return null
}
else {
return { hasWhites: true };
}
}
ngAfterViewChecked() {
this.cdRef.detectChanges();
}
limpiar() {
}
onClick() {
return null;
}
component.css:
/* some stuff...*/
:host /deep/ .control input.ng-invalid.ng-touched {
border-color: #ff8080;
}
验证工作正常,也就是说,当字段为空或输入空格时,它们会跳转。我的问题是我必须添加更多的表单控件,如果它包含消息可能会变得难以辨认:
<div *ngIf="((!txtCodigoContrato.valid && (txtCodigoContrato.dirty ||
txtCodigoContrato.touched)) && (txtCodigoContrato.hasError('required') ||
txtCodigoContrato.hasError('hasWhites')))
||
((!txtCodigoContrato2.valid && (txtCodigoContrato2.dirty ||
txtCodigoContrato2.touched)) && (txtCodigoContrato2.hasError('required') ||
txtCodigoContrato2.hasError('hasWhites')))
||
((!txtContrato.valid && (txtContrato.dirty || txtContrato.touched))
&& (txtContrato.hasError('required') || txtContrato.hasError('hasWhites')))
">
有没有什么方法可以通过打字稿来控制这些值,也就是说,每次控件中的值发生变化时,它都由打字稿中的一个函数控制,该函数 returns true or false 如果只要求该功能在我的 div 中的价值?
你可以这样做
this.contratoForm.valueChanges.subscribe(value = > //do something)
如果你愿意,你可以在之前添加一个映射函数,以从你关心的正在变化的表单中获取值
this.contratoForm.valueChanges
.map(values => values.txtCodigoContrato)
.subscribe(txtCodigoContrato = > //do something)
尝试将 valueChanges
与 Array.some()
函数一起使用
hasError: boolean = false;
constructor(private elRef: ElementRef,
private formBuilder: FormBuilder,
private cdRef: ChangeDetectorRef) {
this.createForm();
// listen to all changes on the form
this.contratoForm.valueChanges.subscribe(_ => {
const controllersToCheck = [
'txtCodigoContrato',
'txtCodigoContrato2',
'txtContrato'
];
this.hasError = controllersToCheck.some(ctrlName => {
let ctrl = this.contratoForm.get(ctrlName);
return (ctrl.dirty || ctrl.touched) &&
(ctrl.hasError('required') || ctrl.hasError('hasWhites'));
});
});
}
(检查!ctrl.valid
是多余的,因为如果控制器有错误,那么它是无效的)
HTML:
<div *ngIf="hasError">
<span>check the fields in red, they are required</span>
</div>
更新
如前所述 here
You can also listen to {@link AbstractControl#statusChanges statusChanges} to be notified when the validation status is re-calculated.
我认为它更适合你的情况,所以尝试订阅 statusChanges
事件(而不是 valueChanges
):
this.contratoForm.statusChanges.subscribe( ..........
更新 2
在您的 HTML:
中使用函数<div *ngIf="hasErrors()">
<span>check the fields in red, they are required</span>
</div>
将此函数添加到您的组件 ts 文件中:
hasErrors() {
const controllersToCheck = [
'txtCodigoContrato',
'txtCodigoContrato2',
'txtContrato'
];
return controllersToCheck.some(ctrlName => {
let ctrl = this.contratoForm.get(ctrlName);
return (ctrl.dirty || ctrl.touched) &&
(ctrl.hasError('required') || ctrl.hasError('hasWhites'));
});
}
我创建了一个STACKBLITZ
如果您添加具有相同验证逻辑的新控制器,只需将它们的控件名称添加到 controllersToCheck
数组