internethulk
internethulk

Reputation: 92

How to show filtered result dynamically in table?

I'm using 3 inputs to filter my data with a http request with searchvaluechanges and observable. My problem is to filter the table with the data I get. The table is filled with a http GET when the dashboard is loaded. Currently I'm not sure if mat-table is the best approach. I can't see a way to make it work.

Dashboard.component.html

<div class="row align-items-end">
 <div class="col">
  <input (change)="searchValueChange()" [(ngModel)]="filter.articleNumber" id="search-box" matInput
             placeholder="Articlenumber...">
  <input (change)="searchValueChange()" [(ngModel)]="filter.name" matInput placeholder="Name...">
  <input (change)="searchValueChange()" [(ngModel)]="filter.description" matInput placeholder="Description...">
 </div>
</div>
<div class="row">
 <div class="col">
  <mat-table [dataSource]="articles" class="mat-elevation-z8">
   <!-- ArticleNumber Column -->
    <ng-container matColumnDef="articleNumber">
      <mat-header-cell *matHeaderCellDef> Articlenumber</mat-header-cell>
      <mat-cell *matCellDef="let article"> {{article.articleNumber}} </mat-cell>
     </ng-container>
   </mat-table>
 </div>
</div>

Dashboard.component.ts

export class DashboardComponent implements OnInit {
  public search$: Observable<ArticleSmall[]>;
  public filter: ArticleFilter = {
    articleNumber: '',
    name: '',
    description: ''
  };
  public articles: ArticleSmall[] = [];
  public searchTerms: Subject<any> = new Subject<any>();
  public dataSource = new MatTableDataSource(this.articles);
  public displayedColumns: string[] = ['articleNumber', 'name', 'description', 'actions'];

  constructor(private articleService: ArticleService) {
  }

  public ngOnInit(): void {
    this.getArticles();

    this.search$ = this.searchTerms.pipe(
      debounceTime(300),
      distinctUntilChanged(),
      switchMap(() => this.articleService.search(this.filter.articleNumber, this.filter.name, this.filter.description)));
  }

  public searchValueChange(): void {
    this.searchTerms.next(JSON.stringify(this.filter));
  }
  //this loads all articles with reduced information in the Dashboards Mat-Table
  public getArticles(): void {
    this.articleService.getAllArticles()
      .pipe(
        map((articles: Article[]) => articles.map((article: Article) => {
            const newArticle: ArticleSmall = {
              name: article.name,
              articleNumber: article.articleNumber,
              description: article.description
            };

            return newArticle;
          }
        ))
      ).subscribe((data: ArticleSmall[]) => this.articles = data);
  }
}

Upvotes: 0

Views: 142

Answers (2)

Eldar
Eldar

Reputation: 10790

Well, you need to make a few changes :

  1. Bind your data table to MatTableDataSource
 <mat-table [dataSource]="dataSource" class="mat-elevation-z8">
   <!-- ArticleNumber Column -->
    <ng-container matColumnDef="articleNumber">
      <mat-header-cell *matHeaderCellDef> Articlenumber</mat-header-cell>
      <mat-cell *matCellDef="let article"> {{article.articleNumber}} </mat-cell>
     </ng-container>
   </mat-table>
  1. Subscribe the $search to update MatTableDataSource's data.
 public ngOnInit(): void {
    // previous code
   this.$search.subscribe(data=>{ // I assumed that your service returns the data not response itself.
    this.dataSource.data = data;
   });
  }

Edit 3. Also you need to change your initial load of data as below :

public getArticles(): void {
    this.articleService.getAllArticles()
      .pipe(
        map((articles: Article[]) => articles.map((article: Article) => {
            const newArticle: ArticleSmall = {
              name: article.name,
              articleNumber: article.articleNumber,
              description: article.description
            };

            return newArticle;
          }
        ))
      ).subscribe((data: ArticleSmall[]) => this.dataSource.data = data);
  }

Upvotes: 1

Alberto Valerio
Alberto Valerio

Reputation: 418

Use the this.changeDetectorRefs.detectChanges() function when you get the data inside your subscribe method.

You need to inject ChangeDetectorRefs in the constructor.

You can find more info here

Upvotes: 1

Related Questions