Angular异步验证器异常排查:标题重复校验问题
博客文本创建功能的标题校验问题解决
问题1:控制台显示findAll返回了数据,但existing_titles始终为空
原因:subscribe是异步操作,当执行return of(existing_titles.includes(testedTitle))时,findAll()的订阅逻辑还没完成,existing_titles还是初始的空数组,所以永远返回false。不能用同步逻辑处理异步数据流。
修正后的TextService代码:
export class TextService { private _url = "http://localhost:8080"; private _textsUrl = "http://localhost:8080/texts"; constructor(private _hc: HttpClient) {} // 补充原代码遗漏的HttpClient注入 findAll(): Observable<Text[]> { return this._hc.get<Text[]>(this._textsUrl); } checkIfTitleExists(testedTitle: string): Observable<boolean> { // 用RxJS操作符直接处理异步流,避免订阅后同步返回的问题 return this.findAll().pipe( map(texts => texts.map(t => t.title).includes(testedTitle)) ); } }
问题2:提交按钮被锁定,但错误提示未显示
原因有两点:
- 模板错误Key不匹配:验证器返回的错误标识是
titleAlreadyExists,但模板里写的是alreadyExistingTitle,大小写和名称不一致,导致错误提示无法触发。 - 异步验证处于
pending状态:异步校验过程中,表单控件会处于未完成状态,此时表单整体无效,按钮会被锁定,但错误信息还未生成,就会出现按钮锁死但无提示的情况。
修正后的模板代码:
<form [formGroup]="form" (ngSubmit)="onSubmit()"> <div> <label> Title </label> </div> <div> <input type="text" formControlName="title"> <!-- 补充校验中的状态提示,同时修正错误Key --> <div *ngIf="form.controls.title.pending">正在校验标题...</div> <div *ngIf="form.controls.title.errors?.titleAlreadyExists"> Title already exists </div> </div> <div> <label> Subtitle </label> </div> <div> <input type="text" formControlName="subtitle"> </div> <div> <label> Content </label> </div> <div> <input type="text" formControlName="content"> </div> <p> <button type="submit" [disabled]="!form.valid">Sauvegarder le texte</button> </p> </form>
额外优化建议
为避免输入时频繁触发后端请求,建议在构建表单时给异步验证器加上触发时机配置:
ngOnInit(): void { this.form = this.fb.group({ title: ["", { asyncValidators: [this.alreadyExistingTitle(this._ts)], updateOn: 'blur' // 失去焦点时才触发异步验证,减少无效请求 }], subtitle: [""], content: [""] , }); }
内容的提问来源于stack exchange,提问作者Tamsin-chan
相关产品推荐
相关产品推荐

