无法在Material Datatable中使用AngularFirestore获取对象键

时间:2019-02-01 17:28:50

标签: angular angular-material angularfire angularfire5

我有一个包含3个文档的材料数据表。在这些列中,我有一个编辑列,该列需要获取ID($ key),以便可以路由到 / object:id。

我怀疑这与异步加载有关,但是在尽我最大的能力进行了彻底搜索之后,我还是找不到真正的答案,或者,坦白地说,我真的不知道要搜索什么< / em>关于如何将其合并到数据表中。

<mat-table #table [dataSource]="vehicle1" [trackBy]="trackByUid" matSort>

当我使用集合(可观察)作为我的数据表源时,我能够获取键并显示它们,尽管即使显示内容,它也会使数据表功能无效,例如过滤和排序。

这是我的TS和模板文件:

(我尝试为多个属​​性[uid,$ key]分配相同的值,以确保它不是关键字问题)

import { Component, AfterViewInit, ViewChild } from '@angular/core';
import { MatTableDataSource, MatSort, MatDialog } from '@angular/material';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from '@angular/fire/firestore';
import { StatusDialogComponent } from './status-dialog/status-dialog.component';
import { Vehicle } from '../vehicle';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Component({
    moduleId: module.id,
    selector: 'app-list-vehicles',
    templateUrl: 'list-vehicles.component.html',
    styleUrls: ['list-vehicles.component.scss']
})
export class ListVehiclesComponent implements AfterViewInit {
    vehicleKey: {};
    vehicles$: AngularFirestoreCollection<Vehicle>;
    vehicles: Observable<Vehicle[]>;
    vehicle: AngularFirestoreDocument;
    displayedColumns = ['vin', 'make', 'model', 'status', '$key', 'details', 'edit'];
    dataSource: MatTableDataSource<any>;
    @ViewChild(MatSort) sort: MatSort;

    constructor(
        public afs: AngularFirestore,
        public dialog: MatDialog,
    ) {
        this.vehicles = this.afs.collection(`vehicles`).snapshotChanges().pipe(
            map(actions => {
                return actions.map(a => {
                    const data = a.payload.doc.data() as Vehicle;
                    const $key = a.payload.doc.id;
                    console.log('payload: ' + a.payload.doc.id);
                    data.$key = a.payload.doc.id;
                    data.uid = a.payload.doc.id;
                    if (data.$key === null || data.$key === undefined) {console.log('null.'); } else {console.log('full' + data.$key); }
                    return {$key, ...data};
                });
            })
        );
    }

    ngAfterViewInit(): void {
        this.afs.collection<Vehicle>('vehicles').valueChanges().subscribe(data => {
            this.dataSource = new MatTableDataSource(data);
            this.dataSource.sort = this.sort;
        });

    }

    applyFilter(filterValue: string) {
        filterValue = filterValue.trim();
        filterValue = filterValue.toLowerCase();
        this.dataSource.filter = filterValue;
    }

    openStatusDialog(data): void {
        const dialogRef = this.dialog.open(StatusDialogComponent, {
            width: '400px',
            data: data,
        });
    }
    trackByUid(index, item) {
        return item.uid;
    }
}
<div *ngFor="let veh of vehicles | async">
        {{veh.$key}} <!-- I can fetch the keys here. -->
        </div>
<div *ngIf="vehicles | async as vehicle1">
<button mat-raised-button color="accent"> A Useless Button </button>
<div class="example-header">
  <mat-form-field>
    <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
  </mat-form-field>
</div>
<mat-table #table [dataSource]="dataSource" [trackBy]="trackByUid" matSort>
  <ng-container matColumnDef="vin">
    <mat-header-cell *matHeaderCellDef mat-sort-header>VIN</mat-header-cell>
    <mat-cell *matCellDef="let vehicle"> {{vehicle.vin}} </mat-cell>
  </ng-container>
  <ng-container matColumnDef="make">
    <mat-header-cell *matHeaderCellDef mat-sort-header>Make</mat-header-cell>
    <mat-cell *matCellDef="let vehicle"> {{vehicle.make}} </mat-cell>
  </ng-container>
  <ng-container matColumnDef="model">
    <mat-header-cell *matHeaderCellDef mat-sort-header>Model</mat-header-cell>
    <mat-cell *matCellDef="let vehicle"> {{vehicle.model}} </mat-cell>
  </ng-container>
  <ng-container matColumnDef="status">
    <mat-header-cell *matHeaderCellDef mat-sort-header>Status</mat-header-cell>
    <mat-cell *matCellDef="let vehicle"> {{vehicle.status}} </mat-cell>
  </ng-container>
  <ng-container matColumnDef="$key">
        <mat-header-cell *matHeaderCellDef mat-sort-header>Key</mat-header-cell>
        <mat-cell *matCellDef="let vehicle"> {{vehicle.$key}} </mat-cell>
      </ng-container>
  <ng-container matColumnDef="details">
    <mat-header-cell *matHeaderCellDef mat-sort-header>Details</mat-header-cell>
    <mat-cell *matCellDef="let vehicle"> <button mat-raised-button color="primary" [routerLink]="['/vehicles', vehicle.$key]">
        Details </button> </mat-cell>
  </ng-container>
  <ng-container matColumnDef="edit">
    <mat-header-cell *matHeaderCellDef mat-sort-header>Edit</mat-header-cell>
    <mat-cell *matCellDef="let vehicle"> <button mat-raised-button color="warn" (click)="openStatusDialog(vehicle)">
        Edit </button> </mat-cell>
  </ng-container>
  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row *matRowDef="let row; columns: displayedColumns;" class="animate"></mat-row>
</mat-table>
Json: {{(vehicle1 | json)}} <!-- I can also fetch them here. -->
</div>

这是当我使用“ dataSource”作为数据表源时: enter image description here

这是当我使用observable作为数据表源时: enter image description here

由于我可以使用可观察的异步方式以某种方式获取密钥,因此如何将类似的方法合并到数据表中,以便可以使用数据表获取密钥?是否有另一种方法可以使用我可能会错过的材料数据表导航到集合中的文档?

1 个答案:

答案 0 :(得分:0)

订阅可观察的数据源,而不是订阅集合即可解决此问题。

所以这个:

this.afs.collection<Vehicle>('vehicles').valueChanges().subscribe(data => {
        this.dataSource = new MatTableDataSource(data);
        this.dataSource.sort = this.sort;
    });

被替换为这样:

this.vehicles.subscribe((d) => this.dataSource = new MatTableDataSource(d));