diff --git a/src/material-examples/example-module.ts b/src/material-examples/example-module.ts
index 07bda41ad4ae..2111b28e6845 100644
--- a/src/material-examples/example-module.ts
+++ b/src/material-examples/example-module.ts
@@ -70,6 +70,7 @@ import {PizzaPartyComponent,SnackBarComponentExample} from './snack-bar-componen
import {SnackBarOverviewExample} from './snack-bar-overview/snack-bar-overview-example';
import {SortOverviewExample} from './sort-overview/sort-overview-example';
import {TableBasicExample} from './table-basic/table-basic-example';
+import {TableHttpExample} from './table-http/table-http-example';
import {TableFilteringExample} from './table-filtering/table-filtering-example';
import {TableOverviewExample} from './table-overview/table-overview-example';
import {TablePaginationExample} from './table-pagination/table-pagination-example';
@@ -424,6 +425,12 @@ export const EXAMPLE_COMPONENTS = {
additionalFiles: null,
selectorName: null
},
+ 'table-http': {
+ title: 'Table retrieving data through HTTP',
+ component: TableHttpExample,
+ additionalFiles: null,
+ selectorName: null
+ },
'table-filtering': {
title: 'Table with filtering',
component: TableFilteringExample,
diff --git a/src/material-examples/table-http/table-http-example.css b/src/material-examples/table-http/table-http-example.css
new file mode 100644
index 000000000000..7c989781b575
--- /dev/null
+++ b/src/material-examples/table-http/table-http-example.css
@@ -0,0 +1,57 @@
+/* Structure */
+.example-container {
+ display: flex;
+ flex-direction: column;
+ max-height: 500px;
+ min-width: 300px;
+ position: relative;
+}
+
+.example-header {
+ min-height: 64px;
+ display: flex;
+ align-items: center;
+ padding-left: 24px;
+ font-size: 20px;
+}
+
+.example-table {
+ overflow: auto;
+ min-height: 300px;
+}
+
+.mat-column-title {
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ flex: 1;
+ overflow: hidden;
+}
+
+/* Column Widths */
+.mat-column-number,
+.mat-column-state {
+ max-width: 64px;
+}
+
+.mat-column-created {
+ max-width: 124px;
+}
+
+.example-loading-shade {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 56px;
+ right: 0;
+ background: rgba(0, 0, 0, 0.15);
+ z-index: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.example-rate-limit-reached {
+ color: #980000;
+ max-width: 360px;
+ text-align: center;
+}
\ No newline at end of file
diff --git a/src/material-examples/table-http/table-http-example.html b/src/material-examples/table-http/table-http-example.html
new file mode 100644
index 000000000000..d9c7ce4a79ce
--- /dev/null
+++ b/src/material-examples/table-http/table-http-example.html
@@ -0,0 +1,46 @@
+
+
+
+
+ GitHub's API rate limit has been reached. It will be reset in one minute.
+
+
+
+
+
+
+
+
+
+ Number
+ {{row.number}}
+
+
+
+
+ Title
+ {{row.title}}
+
+
+
+
+ State
+ {{row.state}}
+
+
+
+
+ Created
+ {{row.created.toDateString()}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/material-examples/table-http/table-http-example.ts b/src/material-examples/table-http/table-http-example.ts
new file mode 100644
index 000000000000..a2c9da53161b
--- /dev/null
+++ b/src/material-examples/table-http/table-http-example.ts
@@ -0,0 +1,129 @@
+import {Component, ViewChild} from '@angular/core';
+import {Http, Response} from '@angular/http';
+import {DataSource} from '@angular/cdk';
+import {MdPaginator, MdSort} from '@angular/material';
+import {Observable} from 'rxjs/Observable';
+import 'rxjs/add/operator/first';
+import 'rxjs/add/operator/startWith';
+import 'rxjs/add/operator/catch';
+import 'rxjs/add/operator/switchMap';
+import 'rxjs/add/observable/merge';
+import 'rxjs/add/observable/of';
+import 'rxjs/add/observable/interval';
+import 'rxjs/add/operator/map';
+
+@Component({
+ selector: 'table-http-example',
+ styleUrls: ['table-http-example.css'],
+ templateUrl: 'table-http-example.html',
+})
+export class TableHttpExample {
+ displayedColumns = ['created', 'state', 'number', 'title'];
+ exampleDatabase: ExampleHttpDao | null;
+ dataSource: ExampleDataSource | null;
+
+ @ViewChild(MdPaginator) paginator: MdPaginator;
+ @ViewChild(MdSort) sort: MdSort;
+
+ constructor(http: Http) {
+ this.exampleDatabase = new ExampleHttpDao(http);
+ }
+
+ ngOnInit() {
+ this.dataSource = new ExampleDataSource(this.exampleDatabase!,
+ this.sort, this.paginator);
+ }
+}
+
+export interface GithubIssue {
+ number: string;
+ state: string;
+ title: string;
+ created: Date;
+}
+
+/** An example database that the data source uses to retrieve data for the table. */
+export class ExampleHttpDao {
+ constructor(private http: Http) {}
+
+ getRepoIssues(sort: string, order: string, page: number): Observable {
+ const href = 'https://api.github.com/search/issues';
+ const requestUrl =
+ `${href}?q=repo:angular/material2&sort=${sort}&order=${order}&page=${page + 1}`;
+ return this.http.get(requestUrl);
+ }
+}
+
+/**
+ * Data source to provide what data should be rendered in the table. Note that the data source
+ * can retrieve its data in any way. In this case, the data source is provided a reference
+ * to a common data base, ExampleHttpDao. It is not the data source's responsibility to manage
+ * the underlying data. Instead, it only needs to take the data and send the table exactly what
+ * should be rendered.
+ */
+export class ExampleDataSource extends DataSource {
+ // The number of issues returned by github matching the query.
+ resultsLength: number = 0;
+ isLoadingResults: boolean;
+ isRateLimitReached: boolean;
+
+ constructor(private _exampleDatabase: ExampleHttpDao,
+ private _sort: MdSort,
+ private _paginator: MdPaginator) {
+ super();
+ }
+
+ /** Connect function called by the table to retrieve one stream containing the data to render. */
+ connect(): Observable {
+ const displayDataChanges = [
+ this._sort.mdSortChange,
+ this._paginator.page,
+ ];
+
+ // If the user changes the sort order, reset back to the first page.
+ this._sort.mdSortChange.subscribe(() => {
+ this._paginator.pageIndex = 0;
+ });
+
+ return Observable.merge(...displayDataChanges)
+ .startWith(null)
+ .switchMap(() => {
+ this.isLoadingResults = true;
+ return this._exampleDatabase.getRepoIssues(
+ this._sort.active, this._sort.direction, this._paginator.pageIndex);
+ })
+ .catch(() => {
+ // Catch if the GitHub API has reached its rate limit. Return empty result.
+ this.isRateLimitReached = true;
+ return Observable.of(null);
+ })
+ .map(result => {
+ // Flip flag to show that loading has finished.
+ this.isLoadingResults = false;
+ return result;
+ })
+ .map(result => {
+ if (!result) { return []; }
+
+ this.isRateLimitReached = false;
+ this.resultsLength = result.json().total_count;
+
+ return this.readGithubResult(result);
+ });
+
+
+ }
+
+ disconnect() {}
+
+ private readGithubResult(result: Response): GithubIssue[] {
+ return result.json().items.map(issue => {
+ return {
+ number: issue.number,
+ created: new Date(issue.created_at),
+ state: issue.state,
+ title: issue.title,
+ };
+ });
+ }
+}