Returning Results from Ionic Modals

June 29th 2018 Ionic 2/3

In the previous blogpost, I created a wrapper function for creating an alert in Ionic which returned a promise with user's input. Although alerts in Ionic are quite flexible, you'll eventually encounter a scenario which will require something more: your input might be too complex or you'll want more options for customizing the appearance.

Either way, modal pages will probably be your best choice. There's no reason why modals couldn't be wrapped into a function in a similar manner. You might want to create a modal page so that the user could select one of the available options, for example:

onSelect() {
  this.selectionModal(this.itemList).then(selected => {
    if (selected != null) {
      console.log(`${selected.id} selected`);
    } else {
      console.log('Nothing selected');
    }
  })
}

From the way the function is called, you can't even tell whether an alert or a modal will be displayed. Which is a good thing. The caller doesn't need to know that. The difference will of course be in how the method is implemented:

private selectionModal<T extends Selectable>(items: Array<T>): Promise<T> {
  let resolveFunction: (selectedItem: T) => void;
  let promise = new Promise<T>(resolve => {
    resolveFunction = resolve;
  });
  let modal = this.modalCtrl.create('SelectionModalPage', { items: items });
  modal.onDidDismiss(selectedItem => resolveFunction(selectedItem));
  modal.present();
  return promise;
}

To make the method more reusable, I used a generic type for the list of items to select from. It extends from the Selectable interface which contains the fields required by the modal page to display the data to the user.

export interface Selectable {
  displayName: string;
}

Actual items can contain any number of fields in addition to that.

Modal pages are implemented similarly to regular pages. Our page reads the list of items from the navigation parameters in the same way:

import { Component } from '@angular/core';
import { IonicPage, NavParams, ViewController } from 'ionic-angular';
import { Selectable } from '../home/home';

@IonicPage()
@Component({
  selector: 'page-selection-modal',
  templateUrl: 'selection-modal.html',
})
export class SelectionModalPage {

  items: Array<Selectable>;

  constructor(navParams: NavParams, private viewCtrl: ViewController) {
    this.items = navParams.get('items');
  }

  itemSelected(item: Selectable) {
    this.viewCtrl.dismiss(item);
  }
}

The only difference is, that it closes itself when the user selects an item, passing the selected item back to the caller. In our wrapper function, the returned value is received by the onDidDismiss callback function which then uses the value to resolve the promise.

For the sake of completeness, here's the template for the modal page:

<ion-header>
  <ion-navbar>
    <ion-title>Select an item</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <ion-list>
    <button ion-item *ngFor="let item of items" (click)="itemSelected(item)">
      {{item.displayName}}
    </button>
  </ion-list>
</ion-content>
Copyright
Creative Commons License