Angular - Clear Observable on Click

16,005

Solution 1

Not sure exactly what you are trying to achieve, but, based on your question, it would seem like you would want to do the following:

clearSearch()
{
  this.searchTerms.next('');
}

Depending on what your desired result is though, you could do the following as well:

  initAnimals() {
    if (this.animals$) {
      this.animals.unsubscribe();
    }

    this.animals$ = this.searchTerms.pipe(
      debounceTime(300),
      distinctUntilChanged(),
      switchMap((term: string) => this.animalService.searchAnimals(term)),
    );

    this.animals$.subscribe( )
  }

  ngOnInit() {
    this.initAnimals();
  }

  clearSearch() {
    this.initAnimals();
  }

Solution 2

when you do

this.searchTerms = new Subject<string>();

you are losing the subject that you have configured pipe for in onInit, as this is brand new subject instance.

you can just emit next value to clear it out using subject.next

Share:
16,005
LozBlake15
Author by

LozBlake15

Updated on June 25, 2022

Comments

  • LozBlake15
    LozBlake15 almost 2 years

    Based off the search in the angular.io tour of heroes tutorial, I've created a simple animal search using an observable. It all works fine, however I'd now like to clear the values in the search, and clear the result list, when I select a result.

    I've created a method to clear the input value on clicking the link, expecting that the observable would update and clear, unfortunately that doesn't happen, and the drop down list remains. I've tried reassigning the observable, which works, but then the observable is unsubscribed, something I don't want to do.

    I'm sure this is a case of me not understanding fully how to work with observables yet, so hoping you guys could help me out.

    Thanks, heres my code.

    import { Component, OnInit } from '@angular/core';
    
    import {Observable, Subject} from 'rxjs'
    
    import {
      debounceTime, distinctUntilChanged, switchMap
    } from 'rxjs/operators';
    
    import { AnimalService } from '../services/animal.service';
    import { Animal } from '../models/animal';
    
    @Component({
      selector: 'app-animal-search',
      templateUrl: './animal-search.component.html',
      styleUrls: ['./animal-search.component.css']
    })
    export class AnimalSearchComponent implements OnInit {
      animals$: Observable<Animal[]>;
      private searchTerms = new Subject<string>();
      private searchTerm: string;
    
      constructor(private animalService: AnimalService) { }
    
      search(term: string):void {
        this.searchTerms.next(term);
      }
    
      ngOnInit() {
        this.animals$ = this.searchTerms.pipe(
    
          debounceTime(300),
    
          distinctUntilChanged(),
    
          switchMap((term: string) => this.animalService.searchAnimals(term)),
        );
    
        this.animals$.subscribe( )
      }
    
      clearSearch()
      {
        //PART THAT ISNT WORKING
        this.searchTerm = "";
        this.searchTerms = new Subject<string>();
      }
    
    }
    
    <div id="search-component" class="search-component-container">
      <input #searchBox id="search-box" [(ngModel)]="searchTerm"  (keyup)="search(searchBox.value)" class="search-component-input" />
    
      <ul class="search-result">
        <li *ngFor="let animal of animals$ | async" >
          <a routerLink="/animal/{{animal.id}}" (click)="clearSearch()"> 
            {{animal.Name}}
          </a>
        </li>
      </ul>
    </div>
    
  • Rich
    Rich over 5 years
    I think this.searchTerms.next(''); is the key solution. In your 'second part' you're creating a new Subject and subscription every time the input is cleared, which I don't think is necessary.
  • LozBlake15
    LozBlake15 over 5 years
    I just want to clear the text I typed into the input, and the UL result list which was created by the previous search (as shown in the first picture). If the UL was bound to a simple array id just clear all the items in the array, but as its an observable that's not possible. I'll give .next('') a try!
  • LozBlake15
    LozBlake15 over 5 years
    Worked a treat and so simple, thank you. Just a quick follow up, when this is connect to a http service, would this cause an additional server call, or is rxjs clever enough to handle that
  • peinearydevelopment
    peinearydevelopment over 5 years
    On its own, it would trigger another service call, but you would just update your switchMap to something like the following: switchMap((term: string) => { if (term) this.animalService.searchAnimals(term);}) to handle that scenario