如何在Angular 4中将md-table与服务一起使用
我在Angular世界中还很陌生,我正尝试在Angular Material 2和Angular 4中使用新的md-table组件.
I am quite new in the angular world and i'm trying to use the new md-table component in Angular Material 2 with Angular 4.
我已经通过API提供了服务,该API可以检索简单的内容数组. 现在,我正在尝试将此服务用作md-table的数据源,但是我找不到从该服务获取数据的方法(它总是向我返回一个空数组).
I've made a service from an API which retrieves simple arrays of content. Now I'm trying to use this service as a data source for the md-table but I can't find a way to get the data from the service (it always return me an empty array).
请注意,在使用md-table之前,我已经在使用该服务,并且可以正常工作.
Please note that before using md-table, I was using already using the service and it worked normally.
这是组件的代码:
import { Component, OnInit, ViewChild } from '@angular/core';
import {DataSource} from '@angular/cdk';
import {MdPaginator} from '@angular/material';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
import { GroupService } from '../shared/group.service';
import { Group } from '../shared/group';
@Component({
selector: 'app-group-list',
templateUrl: './group-list.component.html',
styleUrls: ['./group-list.component.css'],
providers: [GroupService]
})
export class GroupListComponent implements OnInit{
public DisplayedColumns = ['name', 'email', 'directMembersCount'];
public groupDatabase = new GroupDatabase();
public dataSource : CustomDataSource | any;
@ViewChild(MdPaginator) paginator : MdPaginator;
constructor() {}
ngOnInit() {
this.dataSource = new CustomDataSource(this.groupDatabase, this.paginator);
console.log(this.dataSource);
}
}
export class GroupDatabase implements OnInit {
public dataChange: BehaviorSubject<Group[]> = new BehaviorSubject<Group[]>([]);
get data(): Group[] { return this.dataChange.value }
private _groupService : GroupService
private getAllGroups(){
return this._groupService
.getAllGroups();
}
constructor (){}
ngOnInit() {
this.getAllGroups();
console.log(this.getAllGroups());
}
}
export class CustomDataSource extends DataSource<any> {
constructor(private _groupDatabase = new GroupDatabase(), private _paginator: MdPaginator){
super();
}
connect(): Observable<Group[]> {
const displayDataChanges = [
this._groupDatabase.dataChange,
this._paginator.page
];
return Observable.merge(...displayDataChanges).map(() => {
const data = this._groupDatabase.data.slice();
console.log(data);
const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
return data.splice(startIndex, this._paginator.pageSize);
})
}
disconnect() {}
}
这是HTML的代码:
<md-table #table [dataSource]="dataSource">
<ng-container *cdkColumnDef="name">
<md-header-cell *cdkCellDef>Nom</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.name}} </md-cell>
</ng-container>
<ng-container *cdkColumnDef="email">
<md-header-cell *cdkCellDef>Email</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.email}} </md-cell>
</ng-container>
<ng-container *cdkColumnDef="directMembersCount">
<md-header-cell *cdkCellDef>Nombre de membres</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.directMembersCount}} </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]="groupDatabase.data.length"
[pageIndex]="0"
[pageSize]="25"
[pageSizeOptions]="[5, 10, 25, 100]">
</md-paginator>
以及相关服务:
private groupApiUrl: string;
private groupsApiUrl: string;
private headers: Headers;
constructor(public http:Http, private config: Config) {
this.groupApiUrl = config.serverWithApi + "group";
this.groupsApiUrl = config.serverWithApi + "groups";
this.headers = new Headers();
this.headers.append('Content-Type', 'application/json');
this.headers.append('Accept', 'application/json');
}
public getAllGroups = (): Observable<Group[]> => {
return this.http.get(this.groupsApiUrl)
.map((response: Response) => <Group[]>response.json())
.catch(this.handleError)
}
我不确定如何使用数据源调用服务,这就是为什么我像以前那样做它;使用ngOnInit方法.
I'm not sure how I should call the service using the datasource, that's why I did it as I was doing before; using the ngOnInit method.
感谢您的帮助.
Here's an example of retrieving data through HTTP: https://plnkr.co/edit/mjQbufh7cUynD6qhF5Ap?p=preview
您丢失了一个片段,其中GroupDatabase
不会在dataChange
流上放置任何数据值.它是一个BehaviorSubject
,它以一个空数组开头,但是您不再在其上放置任何数据.这就是为什么表只接收一个空数组的原因.
You are missing a piece where GroupDatabase
does not put any data values on the dataChange
stream. It is a BehaviorSubject
that starts with an empty array but you do not put any more data on it. This is why the table is only receiving an empty array.
首先,要知道ngOnInit
不会被Angular调用,因为GroupDatabase
不是指令,也不属于更改检测周期的一部分.
First, know that ngOnInit
will not be called by Angular since GroupDatabase
is not a directive and is not part of the change detection cycle.
相反,将this.getAllGroups()
移到GroupDatabase
的构造函数.然后订阅其结果:
Instead, move this.getAllGroups()
to the constructor of GroupDatabase
. and then subscribe to its result:
export class GroupDatabase {
public dataChange: BehaviorSubject<Group[]> = new BehaviorSubject<Group[]>([]);
get data(): Group[] { return this.dataChange.value }
constructor(groupService: GroupService) {
groupService.getAllGroups().subscribe(data => this.dataChange.next(data));
}
}
或者,完全摆脱GroupDatabase,让您的CustomDataSource
直接调用GroupService.
Alternatively, get rid of GroupDatabase altogether and have your CustomDataSource
directly call your GroupService.
export class CustomDataSource extends DataSource<Group> {
constructor(
private _groupService: GroupService,
private _paginator: MdPaginator) { }
connect(): Observable<Group[]> {
const displayDataChanges = [
this._groupService.getAllGroups(),
this._paginator.page
];
return Observable.merge(...displayDataChanges).map((data, page) => {
const clonedData = data.slice();
const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
return data.splice(startIndex, this._paginator.pageSize);
})
}
disconnect() {}
}