![](/img/trans.png)
[英]RxJS / Angular: Capture valueChanges of FormControl before subscribing
[英]Angular valueChanges updateOn: blur how to wait before all valuechanges completed before submit
我有一个反应式表单,其中包含我订阅的一些字段。 用户在订阅的控件上输入一个值,选项卡或单击字段(模糊事件),将进行后端/http调用以获取一些附加信息并填充一些其他字段。
这一切都完美无缺。
当用户没有点击字段外而是直接点击我们的保存按钮时,就会出现问题,该按钮在保存之前启动逻辑。 100 次中有 70 次也可以,后端调用足够快以获取附加信息,然后开始保存过程,但其他 30 次我们缺少一些信息。
当然,我可以做一些手动检查和验证器,但我认为必须有一种方法来确保我所有的 valuechange 都没有挂起并确保它们都已完成。
非常感谢!
您可以在 API 正在进行时禁用该按钮。
- 维护一个 boolean 变量并使用点击运算符更新其值。在内部使用switchMap
运算符进行 API 调用,一旦完成,禁用 boolean 值。
this.firstName.valueChanges
.pipe(
tap((x) => (this.isLoading = true)),
switchMap(() => {
return of('xxxx').pipe(delay(2000));
}),
tap((x) => (this.isLoading = false))
)
.subscribe((x) => console.log(x));
- 使用 boolean 变量禁用按钮
<button [disabled]="isLoading">Submit</button>
这样,您的按钮将默认启用,但是一旦用户开始在文本框中输入内容,按钮就会被禁用,直到 API 响应完成。
演示:- https://stackblitz.com/edit/angular-ivy-kheete?file=src%2Fapp%2Fapp.component.ts
注意:- 添加了延迟以展示工作流程。
所以我想我找到了一种解决方案。 也许我可以进一步扩展它,所以我不必将布尔值放在我所有的 valuechanges 函数中,但现在这似乎工作正常。
在我的触发值更改 function 中,我从 boolean 开始设置为 true 以标记我们当前正在进行活动值更改。
例子:
async valueChangeFunc() {
this.activeValueChanges = true;
//await..http call
//more logic
this.activeValueChanges = false;
}
在我提交的 function 中,我将等到活动值更改 boolean 被解析为 false。
例子:
async submitForm() {
await waitFor(() => !this.activeValueChanges);
//mark formcontrols as touched etc.
const values = this.myForm.getRawValue();
const errors = getValidationErrors(this.myForm);
//more logic
}
这一切的关键是以下 function 在继续之前等待
const waitFor = async (condFunc: () => boolean) => {
return new Promise<void>((resolve) => {
if (condFunc()) {
resolve();
}
else {
setTimeout(async () => {
await waitFor(condFunc);
resolve();
}, 100);
}
});
};
希望它可以帮助某人,现在工作 100 次中的 100 次
如果监听 valuechanges 对您的用户体验很重要,而不是为用户设置一个按钮来提交他的更改,则处理起来很棘手。 您可以为此 senario 制作一个开箱即用的 sloution,例如:
JSON.stringify(value):使值易于跟踪其更改。
distinictUntilChanged():不会两次发出相同的值。
debounceTime(500):在本例中,从最后一次发出值后需要经过的时间为 500 毫秒。
JSON.parse(value):将值返回到原来的state。
this.form.valuechanges.pipe(
map(value => JSON.stringify(value),
distinictUntilChanged(),
debounceTime(500),
map(value => JSON.parse(value)))
.subscribe(value => {
...Your Code
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.