Search code examples
angulartypescriptangular-pipe

Dropdown field is calling the function with an API Call indefinitely


I have to populate a dropdown with the response of an API. The thing is that api takes few query parameters X and Y that are based on different fields in the screen that can be changed so I can not call the getCategoryByXandY API once at ngOnInIt().

Currently I have it working but as i select the dropdown, the fetchCategories function is being called again and again causing the API to be spammed. I read at different places that this is causing big performance issues but I cannot figure it out how to do it with Pure Pipes. Can someone help me if that's the right direction? and how so?

Service:

  @Injectable()
  export class CategoryRestService {
      private walletsUrl = 'api/items';
      constructor(
        private http: HttpClient
      ) {}
     ...
     getCategoryByXandY(X: string, Y: string): Observable<CategoryDto[]> {
       const url = `${this.itemUrl}/category/?param1=${X}&param2=${Y}`;
       return this.http.get<CategoryDto[]>(url);
     }
  } 

HTML

    ...
    <mat-form-field fxFlex.gt-sm="31%" *ngIf="isRequired()">
            <mat-label>
                Category
            </mat-label>
            <mat-select
                formControlName="category"
                [required]="isRequired()">

                <mat-option
                    *ngFor="let c of fetchCategories()"
                    [value]="c.id">

                    {{c.name}}
                </mat-option>
            </mat-select>
        </mat-form-field>

Component

 {
   categories: CategoryDto[]

   constructor(
      categoryService: CategoryRestService
   ){ } 

   ...

   fetchCategories() {
       const X = this.getControl('x').value;
       const Y = this.getControl('y').value;
       this.categoryService.getCategoryByXandY(x, y).subscribe(
          categories => {
             categories.filter(category => category.status === 'ACTIVE');
             this.categories = categories;
          }
       );
       return this.categories;
    }
}

UPDATE In Addition to David's suggestion, I had a .valueChange on the form field of x and y to trigger the API and update categories


Solution

  • Change let c of fetchCategories() to let c of categories. Point it to the dataset, not the function.

    HTML

        <mat-form-field fxFlex.gt-sm="31%" *ngIf="isRequired()">
          <mat-label>
              Category
          </mat-label>
          <mat-select
              formControlName="category"
              [required]="isRequired()"
              >
              <mat-option
                  *ngFor="let c of categories"
                  [value]="c.id"
    (click)="selected(c)"
    >
                  {{c.name}}
              </mat-option>
          </mat-select>
        </mat-form-field>
    

    Component

    In the constructor or ngOnInit() add this

    this.fetchCategories()

    In your controller

    selected(value:any){
    console.log('selected value',value);
    }