typescript Angular2 表单控件 valueChanges 可观察完成从未调用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37531619/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:32:19  来源:igfitidea点击:

Angular2 form control valueChanges observable complete never called

javascripttypescriptangularrxjsobservable

提问by EldarGranulo

I'm currently trying to show a simple loader on my search bar while the searching is taking place. I have planned to set a variable in the subscribe callback on the valueChangesobservable from my form control to a value "loading", and to set it to an empty string in the complete callback. However, the complete callback is never called.

我目前正在尝试在搜索时在我的搜索栏上显示一个简单的加载程序。我计划在valueChanges表单控件的observable上的订阅回调中设置一个变量为值“加载”,并在完整回调中将其设置为空字符串。但是,永远不会调用完整的回调。

I have also tried adding a callback to finally on the observable, but it is also never called.

我还尝试在可观察对象的 finally 中添加回调,但它也从未被调用过。

My code:

我的代码:

searchBox: Control = new Control();
loadingClass: string = "";

constructor() {
    this.searchBox.valueChanges
            .debounceTime(400)
            .distinctUntilChanged()
            .subscribe((text: string) => {
                this.imageSearch = text;
                this.loadingClass = "loading";
            }, (err: Error) => {
                console.log(err);
            }, () => {
                this.loadingClass = "";
                console.log("test");
            });
}

采纳答案by EldarGranulo

I figured out that I'm trying the wrong approach. Instead, I realized I had debounceTimeon my observable, so I registered a keyupevent on my input control, and in it set the value of loadingClassto "loading", and in my subscribe I set the value back to an empty string.

我发现我正在尝试错误的方法。相反,我意识到我debounceTime在我的 observable 上有,所以我keyup在我的输入控件上注册了一个事件,并在其中设置了loadingClassto的值"loading",并在我的订阅中将值设置回一个空字符串。

回答by Thierry Templier

It's normal since the observable is never completed. The valueChangesallows you to receive value from your search box. In fact, you want to be notified when the search action is complete.

这是正常的,因为 observable 永远不会完成。将valueChanges允许你收到从搜索框的值。实际上,您希望在搜索操作完成时收到通知。

So I would try something like that, assuming that the searchImageactually does the search and return an observable:

所以我会尝试类似的东西,假设searchImage实际上进行搜索并返回一个可观察的:

constructor() {
  this.searchBox.valueChanges
              .debounceTime(400)
              .distinctUntilChanged()
              .flatMap((text:string) => { // <-------
                this.loadingClass = "loading";
                return this.searchImage(text);
              })
              .subscribe((searchResult) => {
                  this.imageSearch = searchResult;
                  this.loadingClass = ""; // <----
              }, (err: Error) => {
                  console.log(err);
              });
}

See this article for the use of the flatMapoperator:

flatMap操作符的使用见这篇文章:

回答by Luillyfe

I hope this could lead some people to get a better understanding of Angular2 Forms. Angular has two different approaches of building forms (Reactive and Template form). Not being aware of this could lead you to messy apps.

我希望这可以引导一些人更好地理解 Angular2 Forms。Angular 有两种不同的构建表单的方法(反应式和模板表单)。不知道这一点可能会导致您使用杂乱的应用程序。

valuesChagesis a property of the directive NgModel, and the class FormControl(keep it mind that).

valuesChages是指令NgModel和类FormControl的属性(请记住这一点)。

The reactive approaches use the ReactiveFormsModule import(your.module.ts):

反应式方法使用ReactiveFormsModule import(your.module.ts):

import {ReactiveFormsModule} from '@angular/forms';

@NgModule({
  ...
  imports: [
    ...
    ReactiveFormsModule,
    ...
  ],
  ...
})

In this way you can use the [(formControl)]property on your form controls (template.component.html).

通过这种方式,您可以[(formControl)]在表单控件 (template.component.html) 上使用该属性。

<input type="text" class="form-control" id="searchBox"
       required
       [(formControl)]="searchBox"/> 

Template-driven approached (your.module.ts):

接近模板驱动(your.module.ts):

import {FormsModule} from '@angular/forms';

    @NgModule({
      ...
      imports: [
        ...
        FormsModule,
        ...
      ],
      ...
    })

This approached has its own form control properties, ngModel(your.template.ts):

这个方法有自己的表单控件属性,ngModel(your.template.ts):

<input type="text" class="form-control" id="searchBox"
       required
       [(ngModel)]="searchBox"/>