Angular - Clear Observable on Click
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
LozBlake15
Updated on June 25, 2022Comments
-
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 over 5 yearsI 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 over 5 yearsI 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 over 5 yearsWorked 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 over 5 yearsOn 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