htmlangulartypescriptblurngonchanges

angular - blur event not resetting value


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.


Solution

  • 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.