Reputation: 2727
I have an angular component with a material design table where objects are shown. This component gets its data via a datasource. The datasource gets its data from a http-service. The table itself can be filtered.
That's my code, simplified - Feel free to ask for further information on certain things if you need to..
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");
}
}
When I delete a entity from the table, it does not get updated. Where are the objects stored, so I can know what I have to update? I have the feeling that the objects, the HTML gets, are in the constant variable displayDataChanges and I cannot change this?
Thanks for any hints to the right directions..
Upvotes: 0
Views: 1645
Reputation: 3715
You're close, but there are a few things slightly off here:
I don't know of a valid use case for calling connect()
and disconnect()
manually. AFAIK connect()
should only be called once by the table, and disconnect()
is a callback when the table is destroyed in case you need to do any sort of unsubscribing or other cleanup. You can remove those lines from deleteCustomer()
.
displayDataChanges
includes dataService.GetAll()
. That means that when connect()
is called by the table and the result is subscribed to, GetAll()
will run. I doubt this is what you want, since GetAll()
is already called and cached in the constructor of CustomerOverviewService
. You probably want dataService.dataChange
, the BehaviorSubject
, to be part of the displayDataChanges
instead. That means that whenever you call dataChange.next(vals)
, your connect()
Observable will emit a new value, and the table will be updated.
The state of your service does not change when Delete()
is called. Whenever the request completes, you should advance the BehaviorSubject
with next()
to update dataChange
with the new value. You can either sort through the current data
and remove the entry, or you can call GetAll()
again. In either case, next()
the new results into dataChange
so that the table will re-render.
Upvotes: 2