Observables in Angular Kanban component
4 Apr 202311 minutes to read
An Observable
is used extensively by Angular since it provide significant benefits over techniques for event handling, asynchronous programming, and handling multiple values.
Observable binding using async pipe
Kanban data can be consumed from an Observable
object by piping it through an async
pipe. The async
pipe is used to subscribe the observable object and resolve with the latest value emitted by it.
Data binding
The kanban expects an object from the Observable
. The emitted value should be an object with properties result and count.
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { TasksService } from './task.service';
import { DataStateChangeEventArgs, DataSourceChangedEventArgs } from '@syncfusion/ej2-kanban';
import { CardSettingsModel } from '@syncfusion/ej2-angular-kanban';
@Component({
selector: 'app-root',
template: `<ejs-kanban #kanbanObj keyField='Status' [dataSource]='data | async' [cardSettings]='cardSettings' (dataStateChange)= 'dataStateChange($event)' (dataSourceChanged)='dataSourceChanged($event)'>
<e-columns>
<e-column headerText='To Do' keyField='Open'></e-column>
<e-column headerText='In Progress' keyField='InProgress'></e-column>
<e-column headerText='Testing' keyField='Testing'></e-column>
<e-column headerText='Done' keyField='Close'></e-column>
</e-columns>
</ejs-kanban>`,
providers: [TasksService]
})
export class AppComponent implements OnInit {
public data: Observable<DataStateChangeEventArgs>;
public state: DataStateChangeEventArgs;
public cardSettings: CardSettingsModel;
constructor(private service: TasksService) {
this.data = service;
}
public dataSourceChanged(state: DataSourceChangedEventArgs): void {
if (state.requestType === 'cardCreated') { state.endEdit() }
else if (state.requestType === 'cardChanged') { state.endEdit() }
else if (state.requestType === 'cardRemoved') { state.endEdit() }
}
public dataStateChange(state: DataStateChangeEventArgs): void {
this.service.execute(state);
}
public ngOnInit(): void {
let state = { skip: 0, take: 10 };
this.service.execute(state);
this.cardSettings = {
contentField: 'Summary',
headerField: 'Id'
};
}
}
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { DataStateChangeEventArgs } from '@syncfusion/ej2-angular-kanban'
import { Observable } from 'rxjs';
import { Subject } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable()
export class TasksService extends Subject<DataStateChangeEventArgs> {
private BASE_URL = 'https://ej2services.syncfusion.com/production/web-services/api/Kanban';
constructor(private http: Http) {
super();
}
public execute(state: any): void {
this.getData(state).subscribe(x => super.next(x));
}
protected getData(state: DataStateChangeEventArgs): Observable<DataStateChangeEventArgs> {
return this.http
.get(`${this.BASE_URL}`)
.pipe(map((response: any) => response.json()))
.pipe(map((response: any) => (<any>{
result: response
})))
.pipe((data: any) => data);
}
}
You should maintain the same
Observable
instance for every kanban action.
When initial rendering, thedataStateChange
event will not be triggered. You can perform the operation in the ngOnInit if you want the kanban to show the cards.
Perform CRUD operations
The dataSourceChanged
event is triggered to update the kanban data. You can perform the save operation based on the event arguments and you need to call the endEdit
method to indicate the completion of the save operation.
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { TasksService } from './task.service';
import { DataStateChangeEventArgs, DataSourceChangedEventArgs } from '@syncfusion/ej2-kanban';
import { CardSettingsModel } from '@syncfusion/ej2-angular-kanban';
@Component({
selector: 'app-root',
template: `
<ejs-kanban #kanbanObj keyField='Status' [dataSource]='data | async' [cardSettings]='cardSettings' (dataStateChange)= 'dataStateChange($event)' (dataSourceChanged)='dataSourceChanged($event)'>
<e-columns>
<e-column headerText='To Do' keyField='Open'></e-column>
<e-column headerText='In Progress' keyField='InProgress'></e-column>
<e-column headerText='Testing' keyField='Testing'></e-column>
<e-column headerText='Done' keyField='Close'></e-column>
</e-columns>
</ejs-kanban>`,
})
export class AppComponent implements OnInit {
public data: Observable<DataStateChangeEventArgs>;
public state: DataStateChangeEventArgs;
public cardSettings: CardSettingsModel;
constructor(private service: TasksService) {
this.data = service;
}
public dataSourceChanged(state: DataSourceChangedEventArgs): void {
if (state.requestType === 'cardCreated') {
this.crudService.addCard(state).subscribe(() => {
state.endEdit();
});
} else if (state.requestType === 'cardChanged') {
this.crudService.updateCard(state).subscribe(() => {
state.endEdit();
});
} else if (state.requestType === 'cardRemoved') {
this.crudService.deleteCard(state).subscribe(() => {
state.endEdit();
});
}
}
public dataStateChange(state: DataStateChangeEventArgs): void {
this.service.execute(state);
}
public ngOnInit(): void {
let state = { skip: 0, take: 10 };
this.service.execute(state);
this.cardSettings = {
contentField: 'Summary',
headerField: 'Id'
};
}
}
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { DataStateChangeEventArgs } from '@syncfusion/ej2-angular-kanban'
import { Observable } from 'rxjs';
import { Subject } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable()
export class TasksService extends Subject<DataStateChangeEventArgs> {
private BASE_URL = 'https://ej2services.syncfusion.com/production/web-services/api/Kanban';
constructor(private http: Http) {
super();
}
public execute(state: any): void {
this.getData(state).subscribe(x => super.next(x));
}
protected getData(state: DataStateChangeEventArgs): Observable<DataStateChangeEventArgs> {
return this.http
.get(`${this.BASE_URL}`)
.pipe(map((response: any) => response.json()))
.pipe(map((response: any) => (<any>{
result: response
})))
.pipe((data: any) => data);
}
/** POST: add a new record to the server */
addCard(state: DataSourceChangedEventArgs): Observable<Customer> {
return this.http.post<Customer>(this.customersUrl, state.addedRecords[0], httpOptions);
}
/** DELETE: delete the record from the server */
deleteCard(state: any): Observable<Customer> {
const id = state.deletedRecords[0].taskId;
const url = `${this.customersUrl}/${id}`;
return this.http.delete<Customer>(url, httpOptions);
}
/** PUT: update the record on the server */
updateCard(state: DataSourceChangedEventArgs): Observable<any> {
return this.http.put(this.customersUrl, state.changedRecords[0], httpOptions);
}
}