Search code examples
angulartypescriptngforangular-pipe

Angular Pipe returns values, but ngFor won't display them


I have a pipe, that filters my ngFor only with the exact matches, that I pass through by clicking on the filterargument.

Here is my pipe:

transform(werte: any[], kriterium: string, gruppe): any[] {
    if (!werte) {
      return [];
    }
    if (!gruppe || gruppe.length === 0) {
      return werte;
    }
    return werte.filter(it =>
      it[kriterium] === gruppe);
  }

Here is my HTML:

<mat-drawer-container class="example-container">
  <mat-drawer mode="side" opened class="side-nav">
    <!-- <mat-card class="mat-card">Kategorien:</mat-card> -->
    <div *ngFor="let skillGruppe of skillGruppen | unique:'skillGruppe'">
      <button mat-button class="filter">
        <div (click)="filtereSkills(filter.textContent)" #filter>
          {{ skillGruppe.skillGruppe }}
        </div>
      </button>
    </div>
  </mat-drawer>
  <mat-drawer-content>
    <div *ngIf="SKILLS?.length > 0; else noItem">
      <div *ngFor="let skill of SKILLS | filter:'skillGruppe':filterWert">
        <div class="skill">
          <mat-accordion>
            <mat-expansion-panel>
              <mat-expansion-panel-header>
                <mat-panel-title>{{ skill.skillname }} </mat-panel-title>
                <mat-progress-bar
                  class="progress-bar"
                  [value]="skill.skillwert"
                  [color]="'accent'"
                  [mode]="'buffer'"
                ></mat-progress-bar>
                <mat-panel-description> </mat-panel-description>
              </mat-expansion-panel-header>
              <div>{{ skill.skillBeschreibung }}</div>
            </mat-expansion-panel>
          </mat-accordion>
        </div>
      </div>
    </div>
    <ng-template #noItem>
      <app-data-loader></app-data-loader>
    </ng-template>
  </mat-drawer-content>
</mat-drawer-container>

When I click on div with the id filter, I change the value of the variable filterWert. Then I filter my ngFor by this Value. The strange thing is, it worked for some time, but now not anymore and I just don't understand why. When I debug it, I get the values returned from the pipe, but the ngFor won't display them. Where is my mistake I made?


Solution

  • You are trying to make operations on a collection in a *ngFor directive in order to filter your collection than loop throught it.

    The angular documentation appendix on pipes specifies to not use a filter or order operation on an *ngFor directive thtough pipes. (https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe)

    What you can do is filter your data before binding it to your *ngFor directive. For example:

    component.ts

    public ngOnInit(): void {
        requestCollectionFromApi().subscribe(result => {
            skillGruppen = filter(result, 'skillGruppe');
        });
    }
    
    private filter(result: Array, unique: string): Array {
        // Process filter operation here and return new array with filtered data.
    }
    

    Then in your HTML, remove the pipe:

    <div *ngFor="let skillGruppe of skillGruppen">
      <button mat-button class="filter">
         <div (click)="filtereSkills(filter.textContent)" #filter>
             {{ skillGruppe.skillGruppe }}
          </div>
        </button>
    </div>
    

    Hope it helps.