md-table 数据源在删除时不更新
md-table with datasource not updating on delete
我有一个 angular 组件,其中显示了 material 设计 table 对象。该组件通过数据源获取数据。数据源从 http 服务获取数据。 table本身可以过滤。
这是我的代码,经过简化 - 如果需要,请随时询问有关某些事情的更多信息..
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");
}
}
当我从 table 中删除实体时,它不会更新。对象存储在哪里,所以我可以知道我必须更新什么?我感觉 HTML 得到的对象在常量变量 displayDataChanges 中,我无法更改它?
感谢您提供正确方向的任何提示..
你已经很接近了,但这里有些地方略有不同:
我不知道手动调用 connect()
和 disconnect()
的有效用例。 AFAIK connect()
只应被 table 调用一次 ,并且 disconnect()
是 table 被销毁时的回调,以防万一需要进行任何类型的取消订阅或其他清理工作。您可以从 deleteCustomer()
.
中删除这些行
displayDataChanges
包括 dataService.GetAll()
。这意味着当 table 调用 connect()
并订阅结果时,GetAll()
将 运行。我怀疑这是你想要的,因为 GetAll()
已经被调用并缓存在 CustomerOverviewService
的构造函数中。您可能希望 dataService.dataChange
、BehaviorSubject
成为 displayDataChanges
的一部分。这意味着每当你调用 dataChange.next(vals)
,你的 connect()
Observable 将发出一个新值,并且 table 将被更新。
调用 Delete()
时,您的服务状态不会改变。每当请求完成时,您应该使用 next()
推进 BehaviorSubject
以使用新值更新 dataChange
。您可以对当前 data
进行排序并删除该条目,或者您可以再次调用 GetAll()
。在任何一种情况下,next()
都会将新结果转换为 dataChange
,以便 table 将重新呈现。
我有一个 angular 组件,其中显示了 material 设计 table 对象。该组件通过数据源获取数据。数据源从 http 服务获取数据。 table本身可以过滤。
这是我的代码,经过简化 - 如果需要,请随时询问有关某些事情的更多信息..
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");
}
}
当我从 table 中删除实体时,它不会更新。对象存储在哪里,所以我可以知道我必须更新什么?我感觉 HTML 得到的对象在常量变量 displayDataChanges 中,我无法更改它?
感谢您提供正确方向的任何提示..
你已经很接近了,但这里有些地方略有不同:
我不知道手动调用
connect()
和disconnect()
的有效用例。 AFAIKconnect()
只应被 table 调用一次 ,并且disconnect()
是 table 被销毁时的回调,以防万一需要进行任何类型的取消订阅或其他清理工作。您可以从deleteCustomer()
. 中删除这些行
displayDataChanges
包括dataService.GetAll()
。这意味着当 table 调用connect()
并订阅结果时,GetAll()
将 运行。我怀疑这是你想要的,因为GetAll()
已经被调用并缓存在CustomerOverviewService
的构造函数中。您可能希望dataService.dataChange
、BehaviorSubject
成为displayDataChanges
的一部分。这意味着每当你调用dataChange.next(vals)
,你的connect()
Observable 将发出一个新值,并且 table 将被更新。调用
Delete()
时,您的服务状态不会改变。每当请求完成时,您应该使用next()
推进BehaviorSubject
以使用新值更新dataChange
。您可以对当前data
进行排序并删除该条目,或者您可以再次调用GetAll()
。在任何一种情况下,next()
都会将新结果转换为dataChange
,以便 table 将重新呈现。