2017-07-10 17 views
11

Tôi khá mới trong thế giới góc và tôi đang cố gắng sử dụng thành phần md-table mới trong Vật liệu góc 2 với Angular 4.Cách sử dụng md-table với các dịch vụ ở Angular 4

Tôi đã tạo một dịch vụ từ một API để truy xuất các mảng nội dung đơn giản. Bây giờ tôi đang cố gắng sử dụng dịch vụ này làm nguồn dữ liệu cho bảng md nhưng tôi không thể tìm cách lấy dữ liệu từ dịch vụ (nó luôn trả về cho tôi một mảng trống).

Xin lưu ý rằng trước khi sử dụng bảng md, tôi đã sử dụng dịch vụ này và nó hoạt động bình thường.

Đây là mã cho các thành phần:

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() {} 
} 

Dưới đây là mã cho 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> 

Và các dịch vụ liên quan:

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) 
    } 

Tôi không chắc chắn làm thế nào tôi nên gọi dịch vụ bằng cách sử dụng nguồn dữ liệu, đó là lý do tại sao tôi đã làm nó như tôi đã làm trước đây; sử dụng phương thức ngOnInit.

Cảm ơn sự giúp đỡ của bạn.

+0

Có vẻ như tôi không phải là người duy nhất tự hỏi điều này! Một vấn đề về điều đó đã được đăng trên repo góc: [# 5670] (https://github.com/angular/material2/issues/5670) – Helongh

+0

Có vẻ như không có bất kỳ tài liệu nào trên trang web angular.io cụ thể cho DataSource, nó chỉ được tham chiếu khi thảo luận về các chủ đề khác, chẳng hạn như các bảng cdk. Phần tôi đang gặp khó khăn là điền vào DataSource sau khi người dùng thực hiện tìm kiếm. – user2748659

Trả lời

14

Dưới đây là một ví dụ về dữ liệu lấy qua HTTP: https://plnkr.co/edit/mjQbufh7cUynD6qhF5Ap?p=preview


Bạn đang thiếu một mảnh nơi GroupDatabase không đặt bất kỳ giá trị dữ liệu trên dòng dataChange. Nó là một BehaviorSubject bắt đầu bằng một mảng trống nhưng bạn không đặt thêm bất kỳ dữ liệu nào trên đó. Đây là lý do tại sao bảng chỉ nhận được một mảng trống.

Đầu tiên, biết rằng ngOnInit sẽ không được gọi bởi Angular vì GroupDatabase không phải là chỉ thị và không phải là một phần của chu kỳ phát hiện thay đổi.

Thay vào đó, hãy di chuyển this.getAllGroups() tới hàm tạo của GroupDatabase. và sau đó đăng ký vào kết quả của nó:

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)); 
    } 
} 

Ngoài ra, thoát khỏi GroupDatabase hoàn toàn và có CustomDataSource của bạn trực tiếp gọi GroupService của bạn.

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() {} 
} 
+1

Cảm ơn câu trả lời của bạn. Thật vậy, điều này đã giải quyết được vấn đề của tôi, nhưng doc thực sự khiến tôi bối rối! – Helongh

+0

Sử dụng phương pháp đầu tiên với GroupDatabase, cách/khi nào bạn chuyển vào dịch vụ? Xem câu hỏi của tôi tại https://stackoverflow.com/questions/46456808/angular-5-material-table-not-getting-data-from-service/46458726#46458726 để biết thêm chi tiết cụ thể về câu hỏi và để xem những gì tôi đã thử. – Tim

+0

@Andrew: Tôi đang theo dõi ví dụ của bạn về Plunker đang hoạt động tốt với 'GitHub API' nhưng khi tôi thay đổi URL và thêm địa chỉ' http: // localhost: 4000/users', tôi nhận được lỗi sau: 'ERROR TypeError: t.json (...) Bản đồ không phải là một hàm'. Tôi cho rằng nó ảnh hưởng đến phần mã này: 'kết quả trả về.json(). map (issue => {return {....}}); '. Bất kỳ ý tưởng nào cần được khắc phục ở đó? Cảm ơn. –

Các vấn đề liên quan