Returning Results from Ionic Alerts
Alerts are a great way for collecting simple inputs from the user with minimum effort.
The examples in the official documentation contain business logic directly in button handlers which not only makes it difficult to test the code, but is also in conflict with the separation of concerns design principle. Wouldn't it be more convenient if the code for displaying the alert could be wrapped in a separate function returning the value entered by the user? It could then be used like this:
onDelete() {
this.confirmationAlert('Do you really want to delete the entry?').then(confirm => {
if (confirm) {
console.log('Deleted');
} else {
console.log('Canceled');
}
})
}
Since user input is asynchronous, we must return a promise instead of the input value directly. Here's an example of such a method for a simple confirmation dialog:
private confirmationAlert(message: string): Promise<boolean> {
let resolveFunction: (confirm: boolean) => void;
let promise = new Promise<boolean>(resolve => {
resolveFunction = resolve;
});
let alert = this.alertCtrl.create({
title: 'Confirmation',
message: message,
enableBackdropDismiss: false,
buttons: [ {
text: 'No',
handler: () => resolveFunction(false)
}, {
text: 'Yes',
handler: () => resolveFunction(true)
} ]
});
alert.present();
return promise;
}
The main part of it is still the code for constructing the alert. However, we have also returned an unresolved promise to the caller which will be resolved when the user clicks one of the buttons. In this case case a simple boolean value is returned, but the method could easily be modified to return actual user input if that was part of the alert.
The main benefit of this approach is that the code creating the alert can easily be reused since it doesn't need to know how to react to the user's response in each case. Instead of only leaving the message up to the caller, I could easily make the alert more configurable. Or create additional variations of the method for different types of user input and move all of them into a separate provider.
This would also be useful for testing as I could use a mocked implementation of the provider in tests to simulate different user inputs and test different code paths in the calling function.