admin管理员组

文章数量:1287103

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 valueChanges observable from my form control to a value "loading", and to set it to an empty string in the plete callback. However, the plete callback is never called.

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

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");
            });
}

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 valueChanges observable from my form control to a value "loading", and to set it to an empty string in the plete callback. However, the plete callback is never called.

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

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");
            });
}
Share Improve this question edited May 30, 2016 at 19:11 Radim Köhler 124k48 gold badges242 silver badges340 bronze badges asked May 30, 2016 at 18:17 EldarGranuloEldarGranulo 1,6151 gold badge15 silver badges39 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 5

It's normal since the observable is never pleted. The valueChanges allows you to receive value from your search box. In fact, you want to be notified when the search action is plete.

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

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 flatMap operator:

  • https://jaxenter./reactive-programming-http-and-angular-2-124560.html

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

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.

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

The reactive approaches use the 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.ponent.html).

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

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

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

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

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

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

本文标签: javascriptAngular2 form control valueChanges observable complete never calledStack Overflow