3
votes

I implemented mat-select-search component with live search functionality with a help of articles on Angular ngx-mat-select-search Custom Component and ngx-mat-select-search documentation. It was working fine till give it dynamic data.

In Child component, I am getting array of objects

@Input() sites: any[];

And this array is being used by another function in

export class SiteDropdownComponent<T> implements OnInit, OnDestroy, AfterViewInit {    


 ngOnInit(): void {
   // set initial selection
   this.siteCtrl.setValue(this.sites[1]);
   // load the initial site list
   this.filteredSites.next(this.sites.slice());
   // listen for search field value changes
   this.siteFilterCtrl.valueChanges
     .pipe(takeUntil(this.onDestroy))
     .subscribe(() => {
       this.filterSites();
     });}}

I am using it inside Parent component

<app-site-dropdown [siteCtrl]="sitesForm.get('site')" [sites]="sites" (sel)="changeCoun($event)"></app-site-dropdown>

And If I give objects

export class AppComponent implements OnInit, AfterViewInit, OnDestroy {`  

sites: any[] = [
  {id: 'item1', name: 'item1'},
  {id: 'item2', name: 'item2'},
  {id: 'item3', name: 'item3'}
]; 

it is working fine, but If I give sites array by sending request to server to process request with some delay in this format

getSitesList() {
  this.subs.add(this.http.post(this.count, 'url/listSites').subscribe(data => {
  this.sites = data.sites;
  console.log(this.sites);
}));

During delay time SiteDropdownComponent component is being rendered and giving error sites are undefined can not use functions because sites have not been loaded yet in

ngOnInit() {
  // set initial selection
  this.siteCtrl.setValue(this.sites[1]);
  // load the initial site list
  this.filteredSites.next(this.sites.slice());
}

Is there any optimal way or function to solve this ? Calling the functions these functions another part of the code, I am not sure about setTimeOut(). SiteDropdownComponent in detail given in link given above.

2

2 Answers

3
votes

you could use *ngIf to make sure your site-dropdown only gets loaded if sites is set.

<app-site-Dropdown *ngIf="sites" [siteCtrl]="sitesForm.get('site')" [sites]="sites" (sel)="changeCoun($event)"></app-site-dropdown>

To learn more about NgIf take a look at its documentation.


Otherwise not initializing the sites array could be a problem, too. If you are setting your data by your request you have to initialize the array before:

sites: any[] = [];
0
votes

you could also use a setter

export class SiteDropdownComponent<T> implements OnInit, OnDestroy, AfterViewInit {  

  @Input() set sites(sites: T[]){
    this._sites = sites;
    this.initializeFormControls();
  };
  get sites(): T[] {
    return this._sites;
  }
  private _sites: T[];

  private initializeFormControls() {
     // set initial selection
   this.siteCtrl.setValue(this.sites[1]);
   // load the initial site list
   this.filteredSites.next(this.sites.slice());
   // listen for search field value changes
   this.siteFilterCtrl.valueChanges
     .pipe(takeUntil(this.onDestroy))
     .subscribe(() => {
       this.filterSites();
     });}}
  }

}

that way the input can change at any moment