title: Angular Material Data Table with sorting, pagination, and filtering using Firestore
body: <p>I currently have a table that is being populated with data coming from Firestore.  I'm having trouble implementing sorting, pagination, and filtering to this and I was hoping someone could shed some light on this for me.  Below is my service, component, and html.  I've seen the different examples on material.angular.io but the example database they use throws me off.</p>
  
  <p><strong>service:</strong></p>
  
  <pre><code>import { Injectable } from '@angular/core';
  import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
  import { Account } from './../models/account.model';
  import { Observable } from 'rxjs/Observable';
  
  @Injectable()
  export class AccountService {
    accountsCollection: AngularFirestoreCollection&lt;Account&gt;;
    accounts: Observable&lt;Account[]&gt;;
  
    constructor(public afs: AngularFirestore) {
      this.accountsCollection = afs.collection('accounts');
  
      this.accounts = this.accountsCollection.snapshotChanges().map(changes =&gt; {
        return changes.map(a =&gt; {
          const data = a.payload.doc.data() as Account;
          data.id = a.payload.doc.id;
          return data;
        });
      });
    }
  
    getAccounts() {
      return this.accounts;
    }
  
   }
  </code></pre>
  
  <p><strong>component:</strong></p>
  
  <pre><code>import { Account } from './../../../models/account.model';
  import { Component, ViewChild, OnInit } from '@angular/core';
  import { DataSource } from '@angular/cdk/collections';
  import { MatPaginator, MatSort } from '@angular/material';
  import { Observable } from 'rxjs/Observable';
  import { AccountService } from '../../../services/account.service';
  
  @Component({
    selector: 'app-account-table',
    templateUrl: './account-table.component.html',
    styleUrls: ['./account-table.component.css']
  })
  export class AccountTableComponent implements OnInit {
    dataSource = new AccountDataSource(this.accountService);
    displayedColumns = [
      'salesStep',
      'status',
      'idn',
      'hospital',
      'state',
      'regionalManager',
      'accountExecutive',
      'clientLiaison',
      'gpo'
    ];
  
    constructor(private accountService: AccountService) {}
  
    ngOnInit() {
  
    }
  
  }
  
  export class AccountDataSource extends DataSource&lt;any&gt; {
  
    constructor(private accountService: AccountService) {
      super();
    }
  
    connect(): Observable&lt;Account[]&gt; {
      return this.accountService.getAccounts();
    }
  
    disconnect() {}
  
  }
  </code></pre>
  
  <p><strong>html:</strong></p>
  
  <pre><code>&lt;div class="example-header"&gt;
    &lt;mat-form-field&gt;
      &lt;input matInput #filter placeholder="Search"&gt;
    &lt;/mat-form-field&gt;
  &lt;/div&gt;
  
  &lt;mat-card class="example-container"&gt;
  
    &lt;mat-table #table [dataSource]="dataSource" matSort&gt;
  
      &lt;!--- Note that these columns can be defined in any order.
            The actual rendered columns are set as a property on the row definition" --&gt;
  
      &lt;!-- Sales Step Column --&gt;
      &lt;ng-container matColumnDef="salesStep"&gt;
        &lt;mat-header-cell *matHeaderCellDef mat-sort-header&gt; Sales Step &lt;/mat-header-cell&gt;
        &lt;mat-cell *matCellDef="let row"&gt; {{row.salesStep}} &lt;/mat-cell&gt;
      &lt;/ng-container&gt;
  
      &lt;!-- Status Column --&gt;
      &lt;ng-container matColumnDef="status"&gt;
        &lt;mat-header-cell *matHeaderCellDef mat-sort-header&gt; Status &lt;/mat-header-cell&gt;
        &lt;mat-cell *matCellDef="let row"&gt; {{row.status}} &lt;/mat-cell&gt;
      &lt;/ng-container&gt;
  
      &lt;!-- IDN Column --&gt;
      &lt;ng-container matColumnDef="idn"&gt;
        &lt;mat-header-cell *matHeaderCellDef mat-sort-header&gt; IDN &lt;/mat-header-cell&gt;
        &lt;mat-cell *matCellDef="let row"&gt; {{row.idn}} &lt;/mat-cell&gt;
      &lt;/ng-container&gt;
  
      &lt;!-- Hospital Column --&gt;
      &lt;ng-container matColumnDef="hospital"&gt;
        &lt;mat-header-cell *matHeaderCellDef mat-sort-header&gt; Hospital &lt;/mat-header-cell&gt;
        &lt;mat-cell *matCellDef="let row"&gt; {{row.hospital}} &lt;/mat-cell&gt;
      &lt;/ng-container&gt;
  
      &lt;!-- State Column --&gt;
      &lt;ng-container matColumnDef="state"&gt;
        &lt;mat-header-cell *matHeaderCellDef mat-sort-header&gt; State &lt;/mat-header-cell&gt;
        &lt;mat-cell *matCellDef="let row"&gt; {{row.state}} &lt;/mat-cell&gt;
      &lt;/ng-container&gt;
  
      &lt;!-- Regional Manager Column --&gt;
      &lt;ng-container matColumnDef="regionalManager"&gt;
        &lt;mat-header-cell *matHeaderCellDef mat-sort-header&gt; RM &lt;/mat-header-cell&gt;
        &lt;mat-cell *matCellDef="let row"&gt; {{row.regionalManager}} &lt;/mat-cell&gt;
      &lt;/ng-container&gt;
  
      &lt;!-- Account Executive Column --&gt;
      &lt;ng-container matColumnDef="accountExecutive"&gt;
        &lt;mat-header-cell *matHeaderCellDef mat-sort-header&gt; AE &lt;/mat-header-cell&gt;
        &lt;mat-cell *matCellDef="let row"&gt; {{row.accountExecutive}} &lt;/mat-cell&gt;
      &lt;/ng-container&gt;
  
      &lt;!-- Client Liaison Column --&gt;
      &lt;ng-container matColumnDef="clientLiaison"&gt;
        &lt;mat-header-cell *matHeaderCellDef mat-sort-header&gt; CL &lt;/mat-header-cell&gt;
        &lt;mat-cell *matCellDef="let row"&gt; {{row.clientLiaison}} &lt;/mat-cell&gt;
      &lt;/ng-container&gt;
  
      &lt;!-- GPO Column --&gt;
      &lt;ng-container matColumnDef="gpo"&gt;
        &lt;mat-header-cell *matHeaderCellDef mat-sort-header&gt; GPO &lt;/mat-header-cell&gt;
        &lt;mat-cell *matCellDef="let row"&gt; {{row.gpo}} &lt;/mat-cell&gt;
      &lt;/ng-container&gt;
  
  
  
      &lt;mat-header-row *matHeaderRowDef="displayedColumns"&gt;&lt;/mat-header-row&gt;
      &lt;mat-row *matRowDef="let row; columns: displayedColumns;"&gt;
      &lt;/mat-row&gt;
    &lt;/mat-table&gt;
  
    &lt;!-- &lt;div class="example-no-results"
         [style.display]="dataSource.renderedData.length == 0 ? '' : 'none'"&gt;
      No accounts found matching filter.
    &lt;/div&gt; --&gt;
  
    &lt;mat-paginator #paginator
                  [length]="(accountService.accounts | async)?.length"
                  [pageIndex]="0"
                  [pageSize]="25"
                  [pageSizeOptions]="[5, 10, 25, 100]"&gt;
    &lt;/mat-paginator&gt;
  &lt;/mat-card&gt;
  </code></pre>