Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add detailed documentation for using DataSource with MatTable #8227

Closed
walhow opened this issue Nov 3, 2017 · 8 comments · Fixed by #9489
Closed

Add detailed documentation for using DataSource with MatTable #8227

walhow opened this issue Nov 3, 2017 · 8 comments · Fixed by #9489
Assignees
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent

Comments

@walhow
Copy link

walhow commented Nov 3, 2017

Proposal: Add detailed documentation for using DataSource with Material Table. Current documentation on DataSource is very high level. Tutorial level documentation, starting with basic table, then adding sort and paging would be good.

What is the expected behavior?

Level of documentation to make using Mat-Table and DataSources, along with Observables more developer friendly.

What is the current behavior?

Very minimal level of documentation regarding how DataSources work with Mat-Table, pagination, and observables.

What are the steps to reproduce?

Have an AngularJS developer add a Mat-Table to a seed project, and use DataSource, Observable, http.get(), and pagination/sorting on the table. Documentation seems lacking to do this. A tutorial would be great.

What is the use-case or motivation for changing an existing behavior?

Make Angular (4) more accessible to developers for a popular use case (full featured DataTable).

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Latest Angular 4

Is there anything else we should know?

@iamwhitebox
Copy link

iamwhitebox commented Nov 4, 2017

+100

To add to this, I've gotten everything to work except for updating the datatable's dataSource with new data from a service. This is mostly an RxJS, Observable related question.

A real-world use case for this would be a search input where users can search and endpoint, return an array of results, and refresh the datatable - in 2 days I can't figure out how to make this work.

datatable.component.ts

@Component({
	selector: 'mat-datatable',
	styleUrls: ['./datatable.component.scss'],
	templateUrl: './datatable.component.html',
})
export class DatatableComponent {
	displayedColumns = ['id', 'collectionName', 'displayType', 'size'];
	datatableDatabase: SearchDataSet | null;
	dataSource: SearchDataSource | null;

	constructor(
		private searchService: SearchService
	) {
		this.datatableDatabase = new SearchDataSet(searchService);
		this.dataSource = new SearchDataSource(this.datatableDatabase);
	}
}
export class SearchDataSet {
	dataChange: BehaviorSubject<Asset[]> = new BehaviorSubject<Asset[]>([]);
	get data(): object { return this.dataChange.value; }

	constructor(
		private searchService: SearchService
	) { }

	getCollections(): Observable<Asset[]> {
		return this.searchService.getInitialCollections()
			.map(this.searchService.readCollectionResult);
	}
}
export class SearchDataSource extends DataSource<Asset> {
	constructor(
		private _searchDataset: SearchDataSet
	) {
		super();
	}

	/** Connect function called by the table to retrieve one stream containing the data to render. */
	connect(): Observable<Asset[]> {
		return this._searchDataset.dataChange
			.switchMap(() => this._searchDataset.getCollections());

	}

	disconnect() { }
}

search.service.ts

@Injectable()
export class SearchService {
    constructor(
        private apiService: ApiService
    ) { }

    private searchSource = new BehaviorSubject<object>(this.getInitialCollections());

    public currentMessage = this.searchSource.asObservable();

    getInitialCollections() {
        return this.apiService.post('/path/to/your/endpoint/_search');
    }

    search(phrase: string) {
        let results = this.apiService.post('/path/to/your/endpoint/_search', { phrase: phrase })
            .subscribe(data => this.changeMessage(data));
    }

    changeMessage(results: object) {
        this.searchSource.next(results)
    }

    readCollectionResult(result: any): Asset[] {
        return result.data.map(asset => {
            return {
                id: asset.id,
                collectionName: asset.collectionName,
                collectionId: asset.collectionId,
                objectType: asset.objectType,
                displayType: asset.displayType,
                size: asset.size,
                createDate: asset.createDate,
                modifiedDate: asset.modifiedDate,
                publishedDate: asset.publishedDate,
                parentFolderId: asset.parentFolderId
            };
        });
    }
}

@andrewseguin andrewseguin added P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent has pr labels Nov 21, 2017
@andrewseguin
Copy link
Contributor

Working on this now at #8162 - please feel free to add comments to help contribute

@walhow
Copy link
Author

walhow commented Nov 21, 2017

@iamwhitebox: I spent a few days to get this working too. For my service, I used the following approach to make clients aware of updates:
https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service
Inside that service, I used HttpClient to get my data, and store it in an array. RxJS Subjects in the service announce when data is available.

I used the following example for the table setup:
https://stackblitz.com/edit/angular-material2-table?file=app%2Fapp.component.ts
I set up the constructor in that component to have a listener that will respond to data updates, in my case a search (see parent-and-children from angular.io above).

On that notification back in my component, when data is received, I set the passed in array of data to a local instance (which is used to replace the NAMES and COLORS variables from the stackblitz example).
Also in my table component, I added a new method that is called as part of the data subscription, that re-initializes the DataSource when data is received (this.dataSource = new ExampleDataSource()). It works, but there is probably a better way to repopulate the DataSource. A lot of trial and error was involved :)

@jjorbas
Copy link

jjorbas commented Dec 14, 2017

I had lot of troubles trying to use this approach:

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

I could get the table, but to sort the columns was impossible because sort wasn't a known property of Datasource, etc, etc

finally i noted that was using "@angular/material": "^5.0.0-rc0",

Currently I'm working with MatTableDataSource

IMPORTS

import {MatTableDataSource} from '@angular/material';

CLASS VARIABLES

private ELEMENT_DATA: reportInterface[] = [];
public tbDataSource;
public displayedColumns;

and in the constructor

this.dataService.getReport().subscribe(results => {
if(!results)return;
this.ELEMENT_DATA = results;
this.displayedColumns = [.............];
this.tbDataSource = new MatTableDataSource(this.ELEMENT_DATA);
this.tbDataSource.sort = this.sort;
});

and here is my filter function

applyFilter(filterValue: string) {
this.tbDataSource.filter = filterValue;
}

I think this is faster and easier

@martynickel
Copy link

It would have helped me a lot to give the transition steps from a REST data source populating a plain HTML table to a mat-data. Like whitebox (above), i've spent a few hours on this already and haven't found joy

@andrewseguin
Copy link
Contributor

Another PR to improve docs as well as open up the table data source API to allow just normal data arrays and streams that emit arrays. If changes to your data occurs, you have the option to call renderRows rather than changing your data array reference.

#9489

@walhow
Copy link
Author

walhow commented Jan 24, 2018 via email

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants