【问题标题】:Couldn't sort and filter data using angular material无法使用角度材料对数据进行排序和过滤
【发布时间】:2021-11-21 17:59:28
【问题描述】:

我目前正在使用 firebase 作为我的后端来检索数据。除了排序和过滤数据之外,所有工作都正常,包括分页。因为它是基于键而不是值实现的,而我不是确定如何解决它。这是我的代码..

admin-products.ts

import { ProductService } from './../../product.service';
import { Component, OnDestroy, ViewChild, AfterViewInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { Product } from 'src/app/models/product';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import {  MatTableDataSource } from '@angular/material/table';


@Component({
  selector: 'app-admin-products',
  templateUrl: './admin-products.component.html',
  styleUrls: ['./admin-products.component.css']
})
export class AdminProductsComponent implements OnDestroy, AfterViewInit{
  products: Product[] = [];
  subscription: Subscription;


  displayedColumns: string[] = ['title', 'price', 'edit'];
  dataSource = new MatTableDataSource<any>(this.products);
  
  @ViewChild(MatSort) sort: MatSort | any;
  @ViewChild(MatPaginator) paginator: MatPaginator | any;

  constructor(private productService: ProductService) { 
    this.subscription = this.productService.getAll()
    .subscribe(products => {
      this.dataSource.data = products;
      console.log(this.dataSource.data);
    });
  }
  
  ngAfterViewInit(){
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
  }

  applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    this.dataSource.filter = filterValue.trim().toLowerCase();
  }

  ngOnDestroy(){
    this.subscription.unsubscribe();
  }
}

admin-products.html

<div class="container">
    <div class="row">
      <div class="col">
        <h2>Product Management</h2>
      </div>
      <div class="col">
        <a routerLink="/admin/products/new" class="btn btn-primary float-right">New Product</a>
      </div>
    </div><br>
  
    <div class="table-container mat-elevation-z3">
      <div class="table-header">
        <mat-form-field appearance="fill"  class="example-full-width">
          <input #input matInput (keyup)="applyFilter($event)" placeholder="Search...">
        </mat-form-field>
      </div>
  
      <table mat-table [dataSource]="dataSource" matSort >
    
        <!-- Title Column -->
        <ng-container matColumnDef="title">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Title </th>
          <td mat-cell *matCellDef="let product">{{ product.val.title }}</td>
        </ng-container>
    
        <!-- Price Column -->
        <ng-container matColumnDef="price">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Price </th>
          <td mat-cell *matCellDef="let product"> {{ product.val.price | currency:'USD' }} </td>
        </ng-container>
    
        <!-- Edit Column -->
        <ng-container matColumnDef="edit" >
          <th mat-header-cell *matHeaderCellDef></th>
          <td mat-cell *matCellDef="let product"><a [routerLink]="['/admin/products/', product.key]">Edit</a></td>
        </ng-container>
    
        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;">
        </tr>
      </table>
    
      <mat-paginator 
        [pageSize]="10"
        [pageSizeOptions]="[10, 25, 50, 100]">
      </mat-paginator>
    </div>
  
  </div>

这是 product-service.ts 中的 getall() 方法

 getAll(): Observable<Product[] | any>{
    return this.db.list<Product>('/products').snapshotChanges()
    .pipe(
      map((actions: any[]) => {
          return actions.map((action) => ({
            key: action.key,
            val: action.payload.val() as Product,
          }));
      }));
  }

for example in the image, if i do filtering it is filtered on the basis of id provided by the firebase and not the title which was expected.

【问题讨论】:

  • 您的过滤/排序在哪里不起作用?在垫子桌上?
  • 它正在处理键而不是值.. 请检查附件图片
  • 在您的 subscribe 函数中,您需要编写 this.dataSource = new MatTableDataSource(products);,否​​则您只有一个带有属性数据的“对象”,而不是 @987654322 @ - 包含所有属性和方法-。您在定义变量时使用新的 MatTableDataSource,但这只会在开始时创建一个空的 MatTableDataSource。
  • @Eliseo 我也这样做了,但它似乎没有帮助.. 排序和过滤器仍在基于 firebase 生成的随机键而不是其中的值。 .

标签: angular firebase angular-material angularfire angular-material-table


【解决方案1】:

我刚刚将 product.service.ts 中的 getAll 方法更改为这个并且它有效

  getAll(): Observable<Product[] | any>{
    return this.db.list<Product>('/products').snapshotChanges()
    .pipe(
      map(changes => 
        changes.map(c => ({ key: c.payload.key, ...c.payload.val() }))
      )
    );
  }

与前面的代码一样,有两个不同的条目,每个条目都包含键和值,因此过滤器和排序方法会自动获取键并应用于该键,但这样 c 在单个条目中包含(键和值)。 . 因此它起作用了。

【讨论】:

    猜你喜欢
    • 2018-06-22
    • 1970-01-01
    • 2019-12-27
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-16
    • 1970-01-01
    相关资源
    最近更新 更多