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>
