Angular Material 2 数据表连接到 AngularFire2 或 Firebase 服务? [英] Angular Material 2 Data Table Connect to AngularFire2 or Firebase Service?

查看:18
本文介绍了Angular Material 2 数据表连接到 AngularFire2 或 Firebase 服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望它只是即插即用 :-) 我已经为此折腾了几个小时,但我的小实验都没有奏效.md数据表是新的,所以网上还几乎没有神识.找到一种将 Firebase 连接到表格的好方法将是一个好的开始.有什么想法吗?

I wish it was just plug and play :-) I've been thrashing around with this for hours with none of my little experiments working. The md data table is new, so there is almost no divine knowledge on the Web yet. Finding a good way to connect Firebase to the table would be a good start. Any ideas?

目前我有这个设置.我的代码在没有标准 Angular 设置和代码的表格的情况下运行良好,使用 ngFor 并从模板创建列表.因此,代码使用 AngularFire 2 提供来自 Firebase 的数据.尝试新的 md 数据表是问题所在.

Currently I have this setup. My code works great without the table with the standard Angular setup and code, using ngFor and creating a list from a template. So the code delivers the data from Firebase with AngularFire 2. Trying out the new md data table is the problem.

首先,模板不会呈现.我知道我的 NgModule 设置正确,所以我怀疑数据源没有连接并产生这个错误.这是 Chrome 控制台中的错误.

First, the template won't render. I know I have NgModule setup correctly so my suspicion is that the data source isn't connecting and creating this error. This is the error in the Chrome console.

Template parse errors:
Can't bind to 'dataSource' since it isn't a known property of 'md-table'.
1. If 'md-table' is an Angular component and it has 'dataSource' input, then verify that it is part of this module.

我的 members-search.component.html 看起来与官方文档相同,只是我更改了模板绑定:

My members-search.component.html looks identical to the official docs except I changed the template binding:

<md-table #table [dataSource]="dataSource">

<ng-container cdkColumnDef="memberName">
    <md-header-cell *cdkHeaderCellDef> Name </md-header-cell>
    <md-cell *cdkCellDef="let row"> {{member.firstName}} {{ member?.lastName }} </md-cell>
</ng-container>

members-search.component.ts 有以下相关部分:

members-search.component.ts has these relevant parts:

import { DataSource } from '@angular/cdk';

@Injectable()
export class MembersAdminService {

  private members$: FirebaseListObservable<Member[]>;
  private dataSource: DataSource<any>;

  constructor(
      private af: AngularFireDatabase,
      @Inject(FirebaseApp) fb) {
        this.members$ = af.list('Members');
  }

我将这些数据表函数放入我在 members-search.service.ts 中的工作代码中,并在 connect() 中使用了我在该服务的其他地方使用过的相同代码.

And I dropped these data table functions into my working code in members-search.service.ts and used the same code in the connect() that I've been using elsewhere on this service.

// md table dataSource functions.
  public connect(): FirebaseListObservable<any> {
    return this.af.list('Members', {
        query: {
            orderByChild: 'lastName'
        }
    });
    // return this._exampleDatabase.dataChange;
  }

  public disconnect() {}

数据表 docs 和 plunker 在组件中创建了一个数据源和数据库,但如果我已经有了 Firebase,那么大部分内容似乎都没有必要.我正在学习这一切,所以我远不是任何方面的专家,也许我错过了一些东西.

The data table docs and plunker create a data source and database in the component but it seems that most of that isn't necessary if I already have Firebase. I'm learning all this so I'm far from an expert at anything and maybe I'm missing something.

如果您之前还没有进入这个新设置,那么这里是文档.md 表建立在 cdk 表之上,以赋予 cdk 表样式.

If you haven't got into this new setup before then here are the docs. The md table is built on top of the cdk table to give the cdk table the styling.

https://material.angular.io/components/table/overview

https://material.angular.io/guide/cdk-table

推荐答案

当使用 MD Paginator 用于 MD 数据表时,我添加了用于连接到 Firebase 的代码.分页器使服务中的代码更加复杂.大多数代码都在它所属的服务中.享受!

I've added the code for connecting to Firebase when using the MD Paginator for the MD Data Table. The Paginator makes the code in the service more complicated. Most of the code is in the service where it belongs. Enjoy!

import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
import { FirebaseApp } from 'angularfire2';
import { Inject, Injectable } from '@angular/core';

import { MemberModel } from './member-admin.model';
import { SuccessService } from '../../../shared/success.service';

// Data Table imports.
import { MdPaginator } from '@angular/material';
import { DataSource } from '@angular/cdk';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/observable/combineLatest';
import 'rxjs/add/operator/map';


@Injectable()
export class MembersAdminService {

  private membersData$: FirebaseListObservable<MemberModel[]>;

  constructor(
    public af: AngularFireDatabase,
    private successService: SuccessService,

    // For Create and Update functions.
    @Inject(FirebaseApp) fb) {
      this.membersData$ = af.list('Members');
    }

// ... CRUD stuff not relevant to the MD Table ...


// *** MD DATA TABLE SERVICES. ***


@Injectable()
export class MemberDatabase {

    /* Stream that emits whenever the data has been modified. */
    public dataChange: BehaviorSubject<MemberModel[]> = new BehaviorSubject<MemberModel[]>([]);
    get data(): MemberModel[] {
        return this.dataChange.value; }

    // Connection to remote db.
    private database = this.memberAdminService.af.list('Members', {
        query: {
            orderByChild: 'lastName'
        }
    });
    public getMembers(): FirebaseListObservable<MemberModel[]> {
        return this.database;
    }


    constructor(private memberAdminService: MembersAdminService) {
        this.getMembers()
            .subscribe(data => this.dataChange.next(data));
    }
}


@Injectable()
export class MembersAdminSource extends DataSource<MemberModel> {


    constructor(
        private memberDatabase: MemberDatabase,
        private paginator: MdPaginator) {
        super();
    }


    /** Connect function called by the table to retrieve one stream containing the data to render. */
    connect(): Observable<MemberModel[]> {

      const displayDataChanges = [
          this.memberDatabase.dataChange,
          this.paginator.page,
      ];

      return Observable
          .merge(...displayDataChanges) // Convert object to array with spread syntax.
          .map(() => {
              const dataSlice = this.memberDatabase.data.slice(); // Data removed from viewed page.

              // Get the page's slice per pageSize setting.
              const startIndex = this.paginator.pageIndex * this.paginator.pageSize;

              const dataLength = this.paginator.length;  // This is for the counter on the DOM.

              return dataSlice.splice(startIndex, this.paginator.pageSize);
          });
    }
    disconnect() {}
}

all-members.component.ts

ngOnInit 和类属性进行了一些重构.

all-members.component.ts

Did some refactoring in ngOnInit and the class properties.

import { Component, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { Subject } from 'rxjs/Subject';

// For MD Data Table.
import { MdPaginator } from '@angular/material';
import { MembersAdminService, MembersAdminSource, MemberDatabase } from './member-admin.service';

import { ConfirmService } from '../../../shared/confirm.service';
import { MemberModel } from './member-admin.model';


@Component({
  selector: 'app-all-members',
  templateUrl: './all-members.component.html'
})


export class AllMembersComponent implements OnInit {

  membersData: MemberModel[];
  private result: boolean;
  allMembers: MemberModel[];

  // For search
  startAt = new Subject();
  endAt = new Subject();
  lastKeypress: 0;

    // For MD data table.

  // private memberDatabase = new MemberDatabase();  // Requires a param but? Moved to constructor.
  private dataSource: MembersAdminSource | null;
  private displayedColumns = [
      'firstName',
      'lastName',
      'mainSkillTitle',
      'mainSkills',
      'delete',
      'key'
  ];

  @ViewChild(MdPaginator)
  paginator: MdPaginator;

  public dataLength: any; // For member counter on DOM.

  constructor(
      private membersAdminService: MembersAdminService,
      private memberDatabase: MemberDatabase,
      private router: Router,
      private confirmService: ConfirmService
  ) {}

  ngOnInit() {

      this.memberDatabase.getMembers()
          .subscribe(members => {
              this.dataSource = new MembersAdminSource(this.memberDatabase, this.paginator);
              this.dataLength = members;
          });
    }

all-members.component.html

请注意,我在行中有用于删除和编辑的按钮,它们工作正常.诀窍是您需要隐藏列中的数据库键.

all-members.component.html

Notice I have buttons in the rows for delete and edit and they work fine. The trick is you need the database key in a hidden column.

<md-table #table [dataSource]="dataSource">

      <!-- First Name Column -->
      <ng-container cdkColumnDef="firstName">
        <md-header-cell *cdkHeaderCellDef> First Name </md-header-cell>
        <md-cell *cdkCellDef="let row"> {{row.firstName}} </md-cell>
      </ng-container>

      <!-- Las Name Column -->
      <ng-container cdkColumnDef="lastName">
        <md-header-cell *cdkHeaderCellDef> Last Name </md-header-cell>
        <md-cell *cdkCellDef="let row">  {{row.lastName}} </md-cell>
      </ng-container>

      <!-- Title Column -->
      <ng-container cdkColumnDef="mainSkillTitle">
        <md-header-cell *cdkHeaderCellDef> Title </md-header-cell>
        <md-cell *cdkCellDef="let row"> {{row.mainSkillTitle}} </md-cell>
      </ng-container>

      <!-- Main Skills Column -->
      <ng-container cdkColumnDef="mainSkills">
        <md-header-cell *cdkHeaderCellDef> Main Skills </md-header-cell>
        <md-cell *cdkCellDef="let row"> {{row.mainSkills}} </md-cell>
      </ng-container>

      <!-- Delete Buttons Column -->
      <ng-container cdkColumnDef="delete">
        <md-header-cell *cdkHeaderCellDef> Delete / Edit </md-header-cell>
        <md-cell *cdkCellDef="let row">
          <button (click)="deleteMember(row.$key)">Delete</button>
          <button (click)="goToDetailPage(row.$key)">Edit</button>
        </md-cell>
      </ng-container>

      <!-- Database key Column -->

      <ng-container cdkColumnDef="key">
        <md-header-cell *cdkHeaderCellDef class="hiddenField"> Key </md-header-cell>
        <md-cell *cdkCellDef="let row" class="hiddenField"> {{row.$key}} </md-cell>
      </ng-container>


      <md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
      <md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>


    </md-table>
    <md-paginator #paginator
                  [length]="dataLength?.length"
                  [pageIndex]="0"
                  [pageSize]="5"
                  [pageSizeOptions]="[5, 10, 25, 100]">
    </md-paginator>

这篇关于Angular Material 2 数据表连接到 AngularFire2 或 Firebase 服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆