I have a search bar functionality where I use ngOnChanges
to detect the search term change, enabling me to filter through some data. However, if I use the previous search term value again, this change will not be caught. Now I know this makes sense because, effectively, there was no change to the search term property.
It seems when I use the 'x' clear button in the search bar, I can use the same search term once again. However, it's not working if I am to remove focus from the search bar and then try to repeat the search term.
My .ts:
@Component({
selector: 'app-orders-list',
templateUrl: './orders-list.component.html',
styleUrls: ['./orders-list.component.css'],
})
export class OrdersListComponent implements OnChanges, AfterViewInit{
@Input() searchTerm: string; // <----
ngOnChanges(changes: SimpleChanges): void {
// searchTerm comes from parent component, if it changes then a new search is active
// want to detect when the current value equals previous value
if (changes.searchTerm) {
if(changes.searchTerm.currentValue === "") {
/* do stuff */
}
else{
/* do stuff */
}
}
...
}
...
}
The search bar .ts:
@Component({
selector: 'app-toolbar',
templateUrl: './orders-toolbar.component.html',
styleUrls: ['./orders-toolbar.component.css'],
})
export class OrdersToolbarComponent implements OnInit {
@ViewChild('searchInput') searchInput: ElementRef;
@Output() searchTerm = new EventEmitter<string>();
@Output() isSearchActive = new EventEmitter<boolean>();
hideSearchBar: boolean;
searchString: string;
searchStringUpdate = new Subject<string>();
ngOnInit(): void {
this.searchString = "";
this.hideSearchBar = true;
this.searchStringUpdate.pipe(
debounceTime(500),
distinctUntilChanged())
.subscribe(() => {
this.onSearchChange();
}
);
}
resetSearchBar() {
this.searchString = "";
this.onSearchChange();
this.hideSearchBar = true;
this.onSearchBarContext(false);
}
showSearchBar() {
this.searchInput.nativeElement.focus();
this.hideSearchBar = false;
this.onSearchBarContext(true);
}
onSearchChange() {
this.searchTerm.emit(this.searchString);
}
onSearchBarContext(isActive: boolean){
this.isSearchActive.emit(isActive);
}
clearSearch(){
this.searchString = "";
this.onSearchChange();
}
}
And for the search bar .html:
<div id="search" class="hide-searchbar" [ngClass]="{'show-searchbar': this.hideSearchBar === false}">
<input
id="searchbar"
type="search"
autocomplete="off"
[(ngModel)]="searchString"
(ngModelChange)="this.searchStringUpdate.next($event)"
(blur)="resetSearchBar()"
(search)="clearSearch()"
(keydown.escape)="searchInput.blur()"
#searchInput
/>
</div>
...
...
Thanks in advance.
Removing distinctUntilChanged
operator from the subscription inside ngOnInit
did the trick.
Like so:
ngOnInit(): void {
this.searchString = "";
this.hideSearchBar = true;
this.searchStringUpdate.pipe(
debounceTime(500))
.subscribe(() => {
this.onSearchChange();
}
);
}
As the name would suggest, distinctUntilChanged
only emits when the current value is different than the last.