fix: change search debounce to subscribe a subject
This will fix "ERROR TypeError: Invalid event target" because the previous object was not yet created in DOM.
MODIFY
src/app/components/api-card-list/api-card-list.component.html
src/app/components/api-card-list/api-card-list.component.html
<mat-form-field id="search-form-field">
<mat-icon matPrefix color="primary">search</mat-icon>
<input
- id="search-input"
matInput
type="search"
[placeholder]="'MPLACE.SEARCH' | translate"
class="search-input"
- [value]="searchTerm" />
+ [(ngModel)]="searchTerm"
+ (ngModelChange)="searchTermNotifier.next()" />
<button
*ngIf="searchTerm.length > 0"
mat-button

MODIFY
src/app/components/api-card-list/api-card-list.component.ts
src/app/components/api-card-list/api-card-list.component.ts
* imitations under the License.
*/
-import { AfterViewInit, Component, Input, OnInit } from '@angular/core';
+import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { ApiService } from '../../services/api/api.service';
import { PageEvent } from '@angular/material/paginator';
-import { debounceTime, map, switchMap } from 'rxjs/operators';
-import { forkJoin, fromEvent, Observable, of } from 'rxjs';
+import { debounceTime, map, switchMap, takeUntil } from 'rxjs/operators';
+import { forkJoin, Observable, of, Subject } from 'rxjs';
import { SpinnerService } from '../../services/spinner/spinner.service';
import { IApiSummary, ISearchCriteria } from '../../interfaces/ICommunication';
import { ActivatedRoute, Params, Router } from '@angular/router';
@@ -29,12 +29,13 @@ import { IApiSummaryExt } from '../../interfaces/IApiSummaryExt';
templateUrl: './api-card-list.component.html',
styleUrls: ['./api-card-list.component.scss']
})
-export class ApiCardListComponent implements OnInit, AfterViewInit {
+export class ApiCardListComponent implements OnInit, OnDestroy {
apis: IApiSummaryExt[] = [];
totalSize = 0;
ready = false;
error = false;
searchTerm = '';
+ searchTermNotifier = new Subject();
pageIndex = 0;
searchCriteria: ISearchCriteria = {
filters: [
@@ -63,19 +64,13 @@ export class ApiCardListComponent implements OnInit, AfterViewInit {
ngOnInit(): void {
this.apis = [];
this.searchTerm = '';
+ this.initSearchDebounce();
this.handleQueryParams();
}
- ngAfterViewInit(): void {
- const searchBox = document.getElementById('search-input');
- fromEvent(searchBox as HTMLElement, 'keyup')
- .pipe(
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types,@typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-member-access
- map((event: any) => event.currentTarget.value as string),
- debounceTime(300)
- )
- .subscribe((searchStr) => {
- this.searchTerm = searchStr;
+ private initSearchDebounce() {
+ // https://m.clearbluedesign.com/how-to-simple-angular-debounce-using-rxjs-e7b86fde6167
+ this.searchTermNotifier.pipe(debounceTime(300)).subscribe(() => {
this.search(this.searchTerm);
});
}
@@ -139,6 +134,8 @@ export class ApiCardListComponent implements OnInit, AfterViewInit {
this.apiService
.searchApis(this.searchCriteria)
.pipe(
+ // takeUntil cancels the search if a new search input is made
+ takeUntil(this.searchTermNotifier),
// map from SearchResultsBeanApiSummaryBean to IApiSummary[]
map((searchResult) => {
this.totalSize = searchResult.totalSize;
@@ -209,4 +206,8 @@ export class ApiCardListComponent implements OnInit, AfterViewInit {
return of([]) as Observable<IApiSummaryExt[]>;
}
}
+
+ ngOnDestroy(): void {
+ this.searchTermNotifier.complete();
+ }
}

fix: change search debounce to subscribe a subject

This will fix "ERROR TypeError: Invalid event target" because the previous object was not yet created in DOM.