md-table,数据源未在删除时更新

时间:2017-09-04 08:34:12

标签: angular typescript angular-services angular-material2

我有一个带有材质设计表的角度组件,其中显示了对象。该组件通过数据源获取其数据。数据源从http服务获取其数据。表格本身可以过滤。

这是我的代码,简化 - 如果您需要,请随时询问有关某些事项的更多信息..

customer.component.html

<md-input-container floatPlaceholder="never">
    <input mdInput #filter placeholder="Filter customers">
</md-input-container>
<md-table #table [dataSource]="dataSource">
    <ng-container cdkColumnDef="customerid">
        <md-header-cell *cdkHeaderCellDef> ID </md-header-cell>
        <md-cell *cdkCellDef="let row"> {{row.id}} </md-cell>
    </ng-container>
    <ng-container cdkColumnDef="remove">
        <md-header-cell *cdkHeaderCellDef></md-header-cell>
        <md-cell *cdkCellDef="let row"> 
            <button md-button (click)="deleteCustomer(row)">
                Remove Customer
            </button> 
        </md-cell>
    </ng-container>
    <md-header-row *cdkHeaderRowDef="displayedColumns">
    </md-header-row>
    <md-row *cdkRowDef="let row; columns: displayedColumns;">
    </md-row>
</md-table>

customer.component.ts

export class CustomerOverviewComponent implements OnInit {
    public displayedColumns: string[] = [
        "customerid", "remove"
    ];
    public dataSource: CustomerOverviewDataSource | null;
    @ViewChild("filter") filter: ElementRef;

     constructor(private dataService: CustomerOverviewService,
                 private cdRef: ChangeDetectorRef) {
        this.initDataSource(dataService);
    }

    ngOnInit(): void {
        Observable.fromEvent(this.filter.nativeElement, "keyup")
            .debounceTime(150)
            .subscribe(() => {
                if (!this.dataSource) { return; }
                this.dataSource.filter = this.filter.nativeElement.value;
            });
    }

    public deleteCustomer(customer: CustomerOverview): void {
        this.dataSource.disconnect();
        this.dataService
            .Delete(customer.id)
            .subscribe(data => {
                this.error.info(`Customer with Id: ${data._body} deleted!`);
            }, (err) => {
                this.error.error(`Unable to delete customer: ${err.message}`);
            });
        this.dataSource.connect();
    }

    private initDataSource(dataService: CustomerOverviewService): void {
        this.dataSource = new CustomerOverviewDataSource(this.dataService);
    }
}

customer.service.ts

@Injectable()
export class CustomerOverviewService {
    private actionUrl: string;
    private headers: Headers;

    dataChange: BehaviorSubject<CustomerOverview[]> = new BehaviorSubject<CustomerOverview[]>([]);
    get data(): CustomerOverview[] { return this.dataChange.value; }

    constructor(private http: Http, private authHttp: AuthHttpService, public snackBar: MdSnackBar) {

        this.actionUrl = Configuration.API_SERVER + "api/customeroverview/";

        this.headers = new Headers();
        this.headers.append("Content-Type", "application/json; charset=utf-8");
        this.headers.append("Accept", "application/json");
        this.GetAll().forEach(s => this.dataChange.next(s));
    }

    public GetAll = (): Observable<CustomerOverview[]> => {
        return this.authHttp
            .get(this.actionUrl)
            .map((response: Response) => <CustomerOverview[]>response.json())
            .publishReplay(1)
            .refCount();
    }

    public Delete = (id: number): Observable<any> => {
        return this.authHttp.delete(this.actionUrl + id)
            .catch(console.log("Delete Catch"));
    }
}

export class CustomerOverviewDataSource extends DataSource<any> {
    _filterChange = new BehaviorSubject("");
    get filter(): string { return this._filterChange.value; }
    set filter(filter: string) { this._filterChange.next(filter); }

    constructor(private dataService: CustomerOverviewService) {
        super();
    }

    /** Connect function called by the table to retrieve one stream containing the data to render. */
    connect(): Observable<CustomerOverview[]> {
        const displayDataChanges: any = [
            this.dataService.GetAll(),
            this._filterChange,];

        return Observable.merge(...displayDataChanges).map(() => {
            return this.dataService.data.slice().filter((item: CustomerOverview) => {
                let searchStr: string = (item.gender + item.lastname + item.firstname + item.personalnumber
                    + item.consultant + item.hasConsultingEntities).toLowerCase();
                return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
            });
        });
    }

    disconnect(): void {
        console.log("disconnect");
    }
}

当我从表中删除实体时,它不会更新。对象存储在哪里,所以我可以知道我要更新什么?我觉得HTML得到的对象是在常量变量displayDataChanges中,我不能改变它吗?

感谢任何正确方向的提示..

1 个答案:

答案 0 :(得分:2)

你已经关闭,但这里有一些东西:

  1. 我不知道手动调用connect()disconnect()的有效用例。 AFAIK connect()只应在表之后调用,而disconnect()是表,如果您需要进行任何类型的取消订阅或其他清理,则会进行回调。您可以从deleteCustomer()

  2. 中删除这些行
  3. displayDataChanges包含dataService.GetAll()。这意味着当表调用connect()并且订阅结果时,GetAll()将运行。我怀疑这是你想要的,因为GetAll()已经被调用并缓存在CustomerOverviewService的构造函数中。您可能希望dataService.dataChange BehaviorSubject成为displayDataChanges的一部分。这意味着无论何时拨打dataChange.next(vals),您的connect() Observable都会发出新值,表格也会更新。

  4. 调用Delete()时,您的服务状态不会更改。每当请求完成时,您应该使用BehaviorSubject推进next()以使用新值更新dataChange。您可以对当前data进行排序并删除该条目,也可以再次致电GetAll()。在任何一种情况下,next()将新结果导入dataChange,以便表格重新呈现。