0
votes

I have to display if the city enterd by the user in a text box is available or not. For that on ngModelChange of the textbox, I am calling a function onCityChange(). In that function, I am emitting user entered data on rxjs Subject. I have subscribed to that Subject in ngOnInit() method. I also have rxjs switchMap() operator in which I am calling the weather search API (in which I will get city name also) through a service.

Now when I enter a correct city name, the API is firing with that city name with HTTP 200 status. After that I am also able to enter another city name and the API is fired with that city name. When a wrong city name is entered, the API is fired with HTTP 404 status as expected. But after that when I enter a correct city name, no API is fired. That is once the API is fired with non success status, it is not firing again with any city name re-entered. What could be wrong?

Here are the code snippets

weather-search.component.html

<input type="text" name="city" placeholder="Enter City" [(ngModel)]="city" (ngModelChange)="onCityChange();">
City found: <b>{{data.name}}</b>

weather-search.component.ts

    private city: string = '';
    private data: any = {};
    private searchStream = new Subject<string>();

    constructor(private weatherService: WeatherService) { }

    onCityChange(){
        if(this.city)
          this.searchStream.next(this.city);
        else
          this.data = {};
      }

    ngOnInit() {
         this.searchStream
        .debounceTime(500)
        .distinctUntilChanged()
        .switchMap((input: string) => this.weatherService.searchWeatherData(input))
        .subscribe(
          (data) => this.data = data,
          (err) => {
            console.error(err);
            this.data = {};
          })
      }
2

2 Answers

1
votes

This is correct behaviour. When a subscriber receives an error notification it unsubscribes and thus disposes the chain which is exactly what happens in your case.

You know that this.weatherService.searchWeatherData(input) might end with an error so instead of just passing it further you can catch it and replace it with whatever you want. Looks like an empty response is enough:

...
.switchMap((input: string) => this.weatherService.searchWeatherData(input)
  .catch(error => Observable.empty())
)
...

This will catch each error notification and replace it with Observable.empty() before it's merge into the chain.

0
votes

You may make use of fromEvent static method of Observable as follows:

@ViewChild('city') city: ElementRef;



 ngOnInit() {
             Observable.fromEvent(this.city.nativeElement, 'input')
            .debounceTime(500)
            .distinctUntilChanged()
            .switchMap((input: string) => this.weatherService.searchWeatherData(input))
            .subscribe(
              (data) => this.data = data,
              (err) => {
                console.error(err);
                this.data = {};
              })
          }