First, on repository, we have our codes returning a Promise:
getAllItems() : Promise<ItemInfo[]> { return new Promise((resolve, reject) => { this.dbInstance.executeSql("SELECT * FROM Item", []) .then((rs) => { . . . resolve(itemsList); }) .catch((err) => reject(err)); }); };
We also have this on the repository layer that will be used by service layer to know that the database is ready to be used:
private dbReady: BehaviorSubject<boolean> = new BehaviorSubject(false); constructor(private plt: Platform) { this.plt.ready().then(() => { this.initialise() .then(() => { this.dbReady.next(true); }) .catch((err) => console.error(err)); }); } getDatabaseState() { return this.dbReady.asObservable(); }
Then on the service. Notice that we will be using BehaviorSubject type and its next() method to announce to listeners that there's a change.
export class ItemService { // this is a handy variable used to keep the latest data in memory private _itemsData: ItemInfo[] = []; private _items: BehaviorSubject<ItemInfo[]> = new BehaviorSubject<ItemInfo[]>([]); // getter that will be used by the presentation layer to get the items get items(): Observable<ItemInfo[]> { return this._items.asObservable(); } constructor(private databaseService: DatabaseService) { this.databaseService.getDatabaseState().subscribe(ready => { if (ready) { this.databaseService.getAllItems() .then((items) => { this._itemsData = items; this._items.next(this._itemsData); }) .catch(error => { console.error(error); }); } }); } addItemDetails(item: ItemForm) { return new Promise((resolve, reject) => { this.databaseService.insertItemDetails(item) .then((newItemId) => { this._itemsData.push(new ItemInfo(. . .)); this._items.next(this._itemsData); resolve(); }) .catch(error => { console.error(error); reject('Error: item cannot be inserted into database.') }); }); } editItemDetails(item: ItemForm) { return new Promise((resolve, reject) => { this.databaseService.updateItemDetails(item) .then(() => { for (let i of this._itemsData) { if (i.itemId == i.itemId) { . . . } } this._items.next(this._itemsData); resolve(); }) .catch(error => { reject("Error: item cannot be updated in database."); }); }); } // similarly when deleting, the local variable _itemsData will need to be updated then call the BehaviorSubject next() method to tell the listeners that there is a change. }
On our presentation (component .ts file), we use:
export class ListItemsPage implements OnInit { items: Observable<ItemInfo[]>; constructor(private service: ItemService) { } ngOnInit() { this.items = this.service.items; } }
Finally, on the template .html page, we have:
<ion-list> <ion-item *ngFor="let i of items | async"> <ion-label> <div>{{i.name}}</div> </ion-label> </ion-item> </ion-list>