angular - 如果下拉列表自动填充,Angular 9 反应式表单会绕过表单验证
问题描述
所以我正在为用户详细信息制作一个反应式表单。我有 2 个省和市的下拉菜单。在表单初始化之后,省字段有*ngFor
循环,并且根据选择,市选项也将使用*ngFor
. 这是在创建新用户但在编辑时,我已设置patchForm
为自动选择/显示现有的省和市。
在表单的编辑模式中,我尝试更改导致市政府清除现有值并加载选择的省份。如果我不选择自治市,表格仍然有效,但console.log(this.form.value)
我可以看到municipality: null
。
.html 文件
<div class="col-sm-12 col-md-3 col-lg-3 col-xl-3">
<div class="form-group">
<label for="province">Province<span class="text-danger">*</span></label>
<select id="province" class="form-control" formControlName="province" (change)="onProvinceSelect()">
<option value="">Please Select...</option>
<option *ngFor="let province of provinces; let i = index" [value]="province">{{ province }}</option>
</select>
</div>
</div>
<div class="col-sm-12 col-md-3 col-lg-3 col-xl-3">
<div class="form-group">
<label for="municipality">Municipality<span class="text-danger">*</span></label>
<select id="municipality" class="form-control" formControlName="municipality" (change)="onMunicipalitySelect()">
<option value="">Please Select...</option>
<option *ngFor="let municipality of municipalities" [value]="municipality.name">{{ municipality.name }}</option>
</select>
</div>
</div>
TS 文件(初始化形式 - 部分)
municipality: new FormControl(null, Validators.required),
province: new FormControl(null, Validators.required)
(如果表格正在编辑)
this.form.patchValue({
province: 'ABC',
municipality: 'DEF'
});
onProvinceSelect() {
// some filtering of municipality based on province
this.form.value.homeMunicipalityCity = null;
}
截至目前,我在onProvinceSelect()
this.form.patchValue({ homeMunicipalityCity: null });
解决方案
您可以使用管道异步和两个可观察对象来解决。
1.-声明两个可观察对象
province$ = this.service.getProvince();
municipy$;
2.-创建函数创建表单
createForm(data: any) {
data = data || { province: null, municipy: null };
return new FormGroup({
province: new FormControl(data.province),
municipy: new FormControl(data.municipy)
});
}
3.-创建一个函数,返回一个可观察的城市
listenChanges(form:FormGroup) {
return form.get("province").valueChanges.pipe(
distinctUntilChanged(),
startWith(form.value?form.value.province:null),
switchMap(res => this.service.getMunicipy(res)),
tap((res: any[]) => {
if (!res || !res.find(x => x == form.value.municipy))
form.get("municipy").setValue(null);
})
);
}
4.- 创建表单时使用函数listenChanges
this.form = this.createForm({ province: "b", municipy: "bb" });
this.municipy$=this.listenChanges(this.form)
.html
<form *ngIf="form" [formGroup]="form">
Province:
<select formControlName="province">
<option *ngFor="let prov of province$|async" [ngValue]="prov">{{prov}}</option>
</select>
Municipy:
<select formControlName="municipy">
<option *ngFor="let prov of municipy$|async" [ngValue]="prov">{{prov}}</option>
</select>
</form>
<button (click)="changeValues()">Change</button>
堆栈闪电战
更新奖励:如何放置“正在加载..”(*)
如果我们也定义了 Subject
loading$=new Subject<boolean>()
loadingDebounce$=this.loading$.pipe(debounceTime(50))
我们可以在“listenChanges”函数中使用“tap this.loading$.next(true)
”this.loading$.next(false)
listenChanges(form:FormGroup) {
let alive=true;
return form.get("province").valueChanges.pipe(
distinctUntilChanged(),
startWith(form.value?form.value.province:null),
tap(()=>this.loading$.next(true)),
switchMap(res => this.service.getMunicipy(res)),
tap((res: any[]) => {
this.loading$.next(false)
if (!res || !res.find(x => x == form.value.municipy))
form.get("municipy").setValue(null);
})
);
}
而我们的形式就像
<form *ngIf="form" [formGroup]="form">
Province:
<select *ngIf="{data:province$|async} as provinces" formControlName="province">
<ng-container *ngIf="provinces.data">
<option [ngValue]="null" hidden>Select one</option>
<option *ngFor="let prov of provinces.data" [ngValue]="prov">
{{prov}}
</option>
</ng-container>
<option *ngIf="!provinces.data">Loading....</option>
</select>
Municipy:
<ng-container *ngIf="{data:municipy$|async} as municipies">
<ng-container *ngIf="{obs:loadingDebounce$ | async} as loading">
<select formControlName="municipy">
<ng-container *ngIf="!loading.obs">
<option [ngValue]="null" hidden>Select one</option>
<option *ngFor="let prov of municipies.data" [ngValue]="prov">
{{prov}}
</option>
</ng-container>
<option *ngIf="loading.obs">Loading....</option>
</select>
</ng-container>
</ng-container>
</form>
(*) 好吧,简单解释一下这个“外星人” *ngIf="{data:municipy|async}"
。这在Yury Katkov 的博文中得到了很好的解释。这种 if 总是返回 true,因为是一个对象,有时会得到值 {data:null} 有时会得到 {data:[.....]} 所以<ng-container>
总是显示下面的元素
推荐阅读
- swift - 以编程方式更改状态时可以为 NSSwitch 设置动画吗?
- git - 仅当我从某些终端登录时才禁用 git 颜色
- excel - Excel:在一个单元格中查找多个字符串,并在另一个单元格中列出它们,根据单元格中的字符串
- typescript - 如何创建与特定文件映射一起使用的自定义 d 文件
- postgresql - PostgreSQL 更新慢
- java - mediacodec解码器中的无序BufferInfo.presentationTimeUs时间戳
- python - 如何将来自 Postman 的 Json 数据转换为 python 中的整数?
- tailwind-css - 如何让子 div 缩小到父 div 高度?
- flutter - 运行颤振应用程序时“assembleDebug”是什么意思?
- android - 在 android 10 上添加带有 OpenMAX 的新音频编解码器格式时出现问题