【问题标题】:md-table with datasource not updating on delete数据源在删除时不更新的 md 表
【发布时间】:2017-09-04 08:34:11
【问题描述】:

我有一个带有材料设计表的角度组件,其中显示了对象。该组件通过数据源获取其数据。数据源从 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 中,我无法更改它?

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

【问题讨论】:

    标签: angular typescript angular-services angular-material2


    【解决方案1】:

    你已经接近了,但这里有一些事情有点不对:

    1. 我不知道手动调用 connect()disconnect() 的有效用例。 AFAIK connect() 应该只被表调用一次disconnect() 是表被销毁时的回调,以防您需要进行任何类型的取消订阅或其他清理。您可以从deleteCustomer() 中删除这些行。

    2. displayDataChanges 包括dataService.GetAll()。这意味着当表调用connect() 并订阅结果时,GetAll() 将运行。我怀疑这是你想要的,因为GetAll() 已经被调用并缓存在CustomerOverviewService 的构造函数中。您可能希望 dataService.dataChangeBehaviorSubject 成为 displayDataChanges 的一部分。这意味着每当您调用 dataChange.next(vals) 时,您的 connect() Observable 将发出一个新值,并且表格将被更新。

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

    【讨论】:

    • 非常感谢,这解决了问题并且解释得很好。不知何故,我不认识 displayDataChanges 一旦创建就永远不会更新
    猜你喜欢
    • 2014-09-07
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-26
    • 2021-10-27
    相关资源
    最近更新 更多