Angular / Primeng filter request to REST backend leads to infinite loop

179 Views Asked by At

I use primeng table with big data. To handle that I send my filters to the REST backend and show the results in my table. But each filter action ends up in an loop.

Here is my service:

public getMovements(filters?: any): Observable<Movement[]> {

  let uri = this.baseUrl + '?q=' + encodeURIComponent(JSON.stringify(filters));
  return this.httpClient.get<Movement[]>(this.baseUrl, this.httpOptions).pipe(
    map((result: any) => {
      return result._embedded.movements; 
  }));
}

And the component's html code. When I enter manufacturer_name and press enter to filter, the loop starts:

<p-table #dt [value]="movements" [paginator]="true" [rows]="50" [showCurrentPageReport]="true" responsiveLayout="scroll" currentPageReportTemplate="Zeige {first} bis {last} von {totalRecords} Einträgen" [rowsPerPageOptions]="[10,25,50]" styleClass="p-datatable-striped"
  [rowHover]="true" (onFilter)="onFilter($event)" [globalFilterFields]="['inventory_category_name', 'manufacturer_name', 'inventory_no', 'user_display_name', 'inventory_status_name']">
  <ng-template pTemplate="caption">
    <div class="flex flex-wrap gap-2 align-items-center justify-content-between">
      <span class="p-input-icon-left w-full sm:w-20rem flex-order-1 sm:flex-order-0">
                    <i class="pi pi-search"></i>
                    <input pInputText type="text" (input)="onGlobalFilter(dt, $event)" placeholder="Globale Suche" class="w-full" />
                </span>
      <button [routerLink]="'/inventories/movements/edit'" pButton class="p-button-outlined w-full sm:w-auto flex-order-0 sm:flex-order-1" icon="pi pi-user-plus" label="Neu"></button>
    </div>
  </ng-template>
  <ng-template pTemplate="header">
    <tr>
      <th pSortableColumn="inventory_category_name">Movement
        <p-sortIcon field="inventory_category_name"></p-sortIcon>
      </th>
      <th pSortableColumn="manufacturer_name">Modell
        <p-sortIcon field="manufacturer_name"></p-sortIcon>
      </th>
      <th pSortableColumn="inventory_no">Inventar-Nr.
        <p-sortIcon field="inventory_no"></p-sortIcon>
      </th>
      <th pSortableColumn="user_display_name">Mitglied
        <p-sortIcon field="user_display_name"></p-sortIcon>
      </th>
      <th pSortableColumn="inventory_status_name">Status
        <p-sortIcon field="inventory_status_name"></p-sortIcon>
      </th>
      <th pSortableColumn="edit_time" class="text-right">Bearbeitung
        <p-sortIcon field="edit_time"></p-sortIcon>
      </th>

    </tr>
    <tr>
      <th>
        <p-columnFilter type="text" field="inventory_category_name"></p-columnFilter>
      </th>
      <th>
        <p-columnFilter type="text" field="manufacturer_name"></p-columnFilter>
      </th>
      <th>
        <p-columnFilter type="text" field="inventory_no"></p-columnFilter>
      </th>
      <th>
        <p-columnFilter type="text" field="user_display_name"></p-columnFilter>
      </th>
      <th>
        <p-columnFilter type="text" field="inventory_status_name"></p-columnFilter>
      </th>
      <th class="text-right">
        <p-columnFilter type="text" field="editor_display_name"></p-columnFilter>
      </th>

    </tr>
  </ng-template>
  <ng-template pTemplate="body" let-movement>

    <tr>
      <td>{{ movement.inventory_category_name }}</td>
      <td>{{ movement.manufacturer_name }} {{ movement.inventory_movement_name }}</td>
      <td>{{ movement.inventory_no }} {{ movement.inventory_name }}</td>
      <td>{{ movement.user_display_name }}</td>
      <td>{{ movement.inventory_status_name }}</td>
      <td class="text-right">{{ movement.editor_display_name }} {{ movement.edit_time | date: 'dd.MM.yyyy HH:mm'}}</td>

    </tr>


  </ng-template>
</p-table>

And the component's code itself:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Table, TableFilterEvent} from 'primeng/table';
import { Movement } from '../../../api/movement'
import { MovementsService } from '../../../service/movements.service';
import { ConfirmationService, MessageService } from 'primeng/api';
import { ConfirmDialogModule } from 'primeng/confirmdialog';
import { Subject, take } from 'rxjs';

@Component({
    templateUrl: './movementslist.component.html',
    providers: [ConfirmationService, MessageService]
})
export class MovementsListComponent implements OnInit {

    movements: Movement[] = [];

    constructor(
        private movementsService: MovementsService, 
        private router: Router,
        private messageService: MessageService,
        private confirmationService: ConfirmationService,
    ) { }

    ngOnInit() {
        
    }

    onSelect(inventory_movement_id?: number) {
        this.router.navigate(["/inventories/movements/edit", inventory_movement_id]);
    }

    onGlobalFilter(table: Table, event: Event) {
        //not impemented yet
    }

    onFilter(event: TableFilterEvent) {
        
        // Here is the loop section ...
        console.log("onFIlter....");
        
        this.movementsService.getMovements(event.filters).pipe(take(1)).subscribe(data => {
            this.movements = data;
        });
    }

}

I think the problem is related to the observer. I'm not too familiar with the observer-subscriber principle in Angular. I am grateful for any help.

0

There are 0 best solutions below