请在此处参考 stackblitz 中的项目 。
可以看出,我的反应形式的控件为firstNumber、secondNumber和thirdNumber。我需要对表单控件进行验证thirdNumber,使其值不应大于在firstNumber和之间具有最小值的表单控件的值secondNumber。
validateThirdNumber每当表单控件发生更改时,组件中的自定义验证器都可以正常工作thirdNumber,但我需要对表单控件的更改进行验证firstNumber,secondNumber因为验证逻辑也可以根据表单控件的更改
firstNumber而更改secondNumber。
为此,我添加了一个有关表单控件更改的事件firstNumber,并将secondNumber表单控件标记thirdNumber为touched但其验证似乎没有被触发。
那么,如何在表单控件thirdNumber发生变化时触发表单控件firstNumber的验证secondNumber?
另外,为什么this.myFormGroup有时在自定义验证器中未定义(请参阅登录于app.componen.ts)line:22,即使在绑定this到其表单控件声明并this.myFormGroup在 中定义后也是如此 constructor ?
我正在一个包含反应式表单 (FormGroup) 和 valueChanges 订阅的组件上编写单元测试代码,但我还没有弄清楚如何确保 FormGroup 发出 valueChanges 事件。
// In the component under test:
this.formGroup.get('field').valueChanges
.subscribe((obj: any[]) => {
debugger; // BREAKPOINT
dataObject.fieldValues = [ ... ];
... details here should be unimportant ...
});
// In the unit test:
it('should set dataObject from field component', fakeAsync(() => {
[
values: string[] = [ ... ];
component.formGroup.get('field').setValue(values);
component.formGroup.get('field').updateValueAndValidity({ emitEvent: true });
fixture.detectChanges();
tick();
expect(component.dataObject.fieldValues.length).toEqual(values.length);
}));
Run Code Online (Sandbox Code Playgroud)
我无法让单元测试规范命中组件订阅代码中的断点。
背景
仅当该组及其所有子项的所有同步验证均有效时,才会执行 FormGroup 上的异步验证。
问题
我想在所有子项都有效之前在 FormGroup 上执行 asyncValidator。
this.myForm = new FormGroup({
country: [ null, [ Validators.required ] ],
postalCode: [ null ],
unrelatedField1: [ null ],
unrelatedField2: [ Validators.min(123) ]
}, {
validators: [ postalCodeFormat ],
asyncValidators: [ postalCodeExists ]
})
Run Code Online (Sandbox Code Playgroud)
我的自定义 postalCodeExists 验证器需要国家/地区和邮政编码字段。它不关心“unrelatedField2”的有效性。
有什么方法可以手动触发 FormGroup 的异步验证吗?
我的第一个想法
据我所知这是不可能的。
this.myForm.valueChanges.pipe(
map(...etc),
distinctUntilChanges(...etc)
).subscribe(() => {
if (this.myForm.get('country').valid && this.myForm.get('postalCode').valid) {
this.myForm.executeAsyncValidationPlease();
}
});
Run Code Online (Sandbox Code Playgroud)
我的第二个想法
this.myForm = new FormGroup({
countryAndPostalCodeGroup: new FormGroup({
country: [ null, [ Validators.required ] ], …Run Code Online (Sandbox Code Playgroud) 我正在使用Angular 7
我有一个嵌套的反应形式
this.salonProfileForm = this.fb.group({
salonName: new FormControl('', [Validators.required]),
address: this.fb.group({
city: new FormControl('', [Validators.required])
})
});
get f() {
return this.salonProfileForm.controls;
}
Run Code Online (Sandbox Code Playgroud)
我有这样的 HTML 表单
<input type="text" formControlName="salonName" required />
<ng-container *ngIf="submitted && f.salonName.invalid && (f.salonName.dirty || f.salonName.touched)">
<small *ngIf="f.salonName.errors.required">
Salon name is required
</small>
</ng-container>
<div formGroupName="address">
<input type="text" formControlName="city" />
<ng-container *ngIf="submitted && f.city.invalid && (f.city.dirty || f.city.touched)">
<small *ngIf="f.city.errors.required">
city is required
</small>
</ng-container>
</div>
Run Code Online (Sandbox Code Playgroud)
但这会在城市输入ng-container字段上产生错误,如下所示
ERROR TypeError: Cannot read property 'invalid' …Run Code Online (Sandbox Code Playgroud) 当在表单组上使用带有异步验证器的反应式表单时,如果通过patchValue在构造函数或 in 中使用来更改表单组的值ngOnInit- 即使异步验证器可观察完成,表单仍保持PENDING状态。
在示例中,您会看到一个包含两个字段的简单表单,其中指示表单状态和验证器状态。在代码中,ngOnInit我调用patchValue表单,导致表单进入PENDING状态,并调用异步验证器。
异步验证器没有做太多事情,它只是等待 1 秒,然后返回一个null错误对象,基本上表明表单是有效的。您可以在指示中看到验证已完成,但表单仍保持PENDING状态。
ngOnInit如果您在构造函数或对象构造之外的任何时间触发字段值的更改,那么VALID当验证程序完成时,表单会进入状态。如果您将值更改包装在 中,这也适用setTimeout。
难道我做错了什么?这是正常行为,还是 Angular 中的错误?
这是我的 html 代码
<table>
<thead>
<tr class='tableHeader'>
<div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
<td fxFlex="22" class="pr-4">Name</td>
<td fxFlex="15" class="pr-4">Price</td>
<td fxFlex="15" class="pr-4">Loan Term</td>
<td fxFlex="15" class="pr-4">Quantity</td>
<td fxFlex="15" class="pr-4">Deposit</td>
<td fxFlex="15" class="pr-4">Total</td>
</div>
</tr>
</thead>
<tbody>
<tr [formGroup]="loanProductForm">
<div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
<td fxFlex="22">
<mat-form-field appearance="outline" fxFlex="100" class="pr-4">
<mat-label>Product </mat-label>
<mat-select formControlName="productId" required>
<mat-option *ngFor="let product of productList" [value]="product.productId">
{{product.name}}
</mat-option>
</mat-select>
</mat-form-field>
</td>
<td fxFlex="15">
<mat-form-field appearance="outline" fxFlex="100" class="pr-4">
<mat-label>Price </mat-label> …Run Code Online (Sandbox Code Playgroud) 我执行异步服务调用来获取元素列表。
public elementList: Array<Element>;
...
this.service.getElementList().subscribe( list => {
this.elementList = list;
this.createFormGroup(list);
}
);
...
Run Code Online (Sandbox Code Playgroud)
当我收到元素列表(我订阅了服务调用)时,我根据元素列表构建表单组。在模板中,我有一个 *ngIf 仅当列表大于零时才绘制。
*ngIf="elementList?.length>0"
Run Code Online (Sandbox Code Playgroud)
由于elementList是异步获取的,所以这个ngIf不起作用。我读到可以将 ngIf 与 AsnycPipe 一起使用。所以在模板中我将有:
*ngIf="elementList$ && elementList$.length>0"
Run Code Online (Sandbox Code Playgroud)
其中 elementList$ 是从服务调用返回的 Observable。
public elementList$: Observable<Array<Element>>;
elementList$ =this.service.getElementList()
Run Code Online (Sandbox Code Playgroud)
我想知道收到 elementList 后如何创建 FormGroup。首先,我需要创建 FormGroup,然后模板应该调用 *ngIf 来绘制元素。
我是角度单元测试的新手。测试场景:html中的表单视图值等于组件表单值。电子邮件值由共享值检索并在组件注册表单中使用。我可以使用反应式表单从组件中检索电子邮件值,但是当尝试通过本机元素访问时,它给出了空。下面是component.ts
ngOnit(public serviceEmail) {
this.assignEmailAvailable();
this.createRegistration();
}
assignEmailAvailable() {
if(service.email){
this.email = serviceEmail.email;
}
}
createRegistration() {
this.registerForm = new FormGroup({
email:new FormControl({value:this.email})
})
}
Run Code Online (Sandbox Code Playgroud)
在 component.spec.ts 中,我将调用此函数并检查两个值是否相同。组件规格
beforeEach(() => {
fixture = TestBed.createComponent(RegisterComponent);
component = fixture.componentInstance;
service = TestBed.get(serviceEmail);
});
it('Registration Form Creation', fakeAsync(() => {
service.email = "dsf@gmail.com";
fixture.detectChanges();
component.assignEmailAvailable();
component.createRegisterForm();
fixture.detectChanges();
fixture.whenStable().then(() => {
const email = fixture.debugElement.query(By.css('input[id="email"]')).nativeElement;
//The value is empty even after creating the form using the component function
expect(email.value).toBe(component.emailValue);
});
//THis returns me the …Run Code Online (Sandbox Code Playgroud) 您好,我使用反应式表单将对象数组绑定到 formArray,但在这里,如果我选择一个部分中的任何一项,然后单击“向右移动/向左移动”,则整个对象已从一个部分移动到另一部分。但该功能工作正常,但我无法检测到 form.valuechanges() 中从一个部分到其他部分所做的更改。任何人都可以帮助我检测更改,以防项目已从一个部分移动到另一部分,在这里我想要更改检测,但功能必须按原样工作,我的意思是整个对象从一个部分移动到另一部分。
提前致谢。
我这里有工作 demo2,我希望我之前发布的 demo1 能够像这个 demo2 一样工作,并且 formarray 工作。 演示2
演示: 演示 1
TS:
private settingsGroupInfoForm() {
if (!this.agentDetailsList) {
// Add
this.agentGroupViewInfoForm = this.FB.group({
agentGroupView: this.FB.array(
this.agentInView.map(x=>(x))
),
})
} else {
// Edit
if (this.agentDetailsList) {
this.agentGroupViewInfoForm = this.FB.group({
agentGroupView: this.FB.array(this.agentInView.map(x=>(x))),
})
}
this.agentGroupViewInfoForm.valueChanges.subscribe(data => {
this.formEdit = true;
console.log('agentGroupViewInfoForm', this.formEdit)
})
}
}
Run Code Online (Sandbox Code Playgroud)
HTML:
<div class="card-body overflow-auto py-0" *ngIf="agentGroupViewInfoForm"
[formGroup]="agentGroupViewInfoForm">
<ul class="list-group list-group-flush" *ngFor="let child of agentInView" name="agentInGroup" formArrayName="agentGroupView">
<li class="list-group-item {{isInActiveItems(child) ? …Run Code Online (Sandbox Code Playgroud) 我想在表单上添加反应式表单控件,并触发错误:
多个自定义值访问器与具有未指定名称属性的表单控件相匹配
一切都是单独工作的,反应式表单验证,掩码或 matDatepicker,任何组合也可以工作,但三者一起提示错误。
这是我的代码:
在组件.ts中
formGroup = new FormGroup({
date: new FormControl()
});
Run Code Online (Sandbox Code Playgroud)
在组件.html中
<mat-form-field>
<input type="text" matInput [matDatepicker]="date_picker" mask="d0/M0/0000" formControlName="date">
<mat-datepicker-toggle matSuffix [for]="date_picker"></mat-datepicker-toggle>
<mat-datepicker #date_picker></mat-datepicker>
</mat-form-field>
Run Code Online (Sandbox Code Playgroud)
我在用着:
"@angular/cli": "8.3.19"
"ngx-mask": "8.1.7"
"@angular/material": "8.2.3"
Run Code Online (Sandbox Code Playgroud) angular-material angular angular-reactive-forms ngx-mask mat-datepicker