我有一个仅包含一个字段的反应式表单,当用户停止键入时,我想在控制台上打印该值。为此,当字段中的值更改时,我使用debounceTime()
。
我读到了一些与How to use debounceTime in an angular component?和Angular and debounce之类的debounceTime()
的使用有关的问题,但是我的代码多次打印最新值,然后才检测到更改,并且经过了debounceTime函数中的时间
表单的输入字段为:
<input matInput formControlName="name" (keyup)="onInputChange()">
onInputChange函数中的代码是这样的:
this.userForm.get("name").valueChanges
.pipe(
debounceTime(500)
)
.subscribe(res => {
console.log(res)
});
如果输入为test
,则控制台中的结果如下图所示:
怎么了?
答案 0 :(得分:3)
您正在调用一个函数并在每次按键时订阅,您只需要订阅一次即可,而无需调用(keyup)函数,因为这将捕获对输入的任何更改。
似乎正在调用的函数可能导致创建四个订阅,因此在控制台中创建了四个条目。
<input matInput formControlName="name" (keyup)="onInputChange()">
应该是
<input matInput formControlName="name">
将此逻辑移至ngOnInit()
中,以便在组件生命周期的早期创建订阅,并且仅创建一次。
然后您可以对该名称进行无引用复制,并在valuesChanged()
块中进行比较,以确保该名称与发布前的原始名称不匹配。
userForm = this.formBuilder.group({
name: ['']
)};
public originalName = '';
public ngOnInit(): void
{
this.userService.getUserById(this.userId).subscribe(res =>
{
this.originalName = JSON.parse(JSON.stringify(res.name));
this.userForm.controls['name'].setValue(res.name);
this.userForm.get("name").valueChanges.pipe(debounceTime(500)).
subscribe(res =>
{
if (res.name !== this.originalName)
{
// logic to post to server
}
});
});
}
还将建议您阅读有关销毁组件时如何处理订阅的信息,因为这将无法处理其自身,因此有很多可用资源。
答案 1 :(得分:1)
如其他答案中所述,没有keyup
处理程序。只需听valueChanges
。由于您要发出http请求,因此我们可以使用switchMap
。还请记住退订valueChanges
。如果用户仅键入空白,我们也可能希望过滤掉。所以我建议如下:
import { Subscription } from 'rxjs';
import { debounceTime, switchMap, filter } from 'rxjs/operators';
// ...
formSub = new Subscription();
ngOnInit() {
this.formSub = this.userForm.get('name').valueChanges.pipe(
debounceTime(500),
filter(value => !!value.trim()),
switchMap((value) => {
// replace with your request
return this.myService.postData(value)
})
// replace MyInterface with your model
).subscribe((data: MyInterface) => console.log(data))
}
ngOnDestroy() {
this.formSub.unsubscribe();
}
然后以编程方式设置该值时出现问题。我们可以使用emitEvent: false
,它不会导致valueChanges
触发:
this.userForm.get('name').setValue('my name', { emitEvent: false })