Recently I was prototyping an application in NativeScript with Angular, but was feeling too lazy to set up the Angular Router to do multiple page navigation. Typically when I run into this scenario I use the prompt dialog, but this time I needed something more than data input. This lead me to the modal dialog.
With the modal dialog I can create a popup with pretty much anything on it and when I close it I can pass data back to the parent view. We’re going to see how to use a custom modal within our iOS and Android NativeScript application built with Angular.
Instead of seeing bits and pieces, we’re going to build a new project from scratch. From the Terminal or Command Line, execute the following:
tns create ModalProject --ng
cd ModalProject
tns platform add android
tns platform add ios
The --ng
flag indicates that we are going to be developing with Angular and TypeScript. To build for iOS you need to be using a Mac with Xcode installed, otherwise the Android platform works pretty much anywhere.
The goal is to create an application that looks like the following animated image:
A button will appear on the screen and when pressed will display a list of options. When items in the list are pressed, they are passed back to the original page. This particular project uses no plugins or libraries so at this point we can start developing.
Even though we won’t be using the Angular Router, we’re still going to be creating an HTML and TypeScript file to represent our modal.
If using a Mac or Linux computer, execute the following:
touch app/app.modal.ts
touch app/app.modal.html
If you’re using a Windows computer, just create those files manually.
Starting with the TypeScript logic, open the project’s app/app.modal.ts file and include the following TypeScript code:
import { Component } from "@angular/core";
import { ModalDialogParams } from "nativescript-angular/directives/dialogs";
@Component({
selector: "my-modal",
templateUrl: "app.modal.html",
})
export class ModalComponent {
public frameworks: Array<string>;
public constructor(private params: ModalDialogParams) {
this.frameworks = [
"NativeScript",
"Xamarin",
"Onsen UI",
"Ionic Framework",
"React Native"
];
}
public close(res: string) {
this.params.closeCallback(res);
}
}
The above ModalComponent
class has a public array which will be bound to the UI of the modal. That array is populated via the constructor
method. When we wish to close the modal we can pass data to the parent view. Both of this is done through the closeCallback
method of the ModalDialogParams
service.
Now we can focus on the UI for the modal. Open the project’s app/app.modal.html file and include the following XML markup:
<GridLayout backgroundColor="white">
<ListView [items]="frameworks" class="list-group">
<Template let-framework="item">
<StackLayout class="list-group-item" (tap)="close(framework)">
<Label text="{{ framework }}" class="label"></Label>
</StackLayout>
</Template>
</ListView>
</GridLayout>
The UI has a list where each item of the list comes from the frameworks
array found in the TypeScript code. When tapping an item in the list, the close
method is called and the value is passed.
For the modal to work, it needs to be injected into the project’s @NgModule
block found in the app/app.module.ts file. Open this file and include the following code:
import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptModule } from "nativescript-angular/platform";
import { ModalDialogService } from "nativescript-angular/modal-dialog";
import { AppComponent } from "./app.component";
import { ModalComponent } from "./app.modal";
@NgModule({
declarations: [AppComponent, ModalComponent],
entryComponents: [ModalComponent],
bootstrap: [AppComponent],
imports: [
NativeScriptModule
],
providers: [ModalDialogService],
schemas: [NO_ERRORS_SCHEMA]
})
export class AppModule { }
Notice that we’re importing the ModalDialogService
and injecting it into the declarations
and entryComponents
arrays of the @NgModule
block.
Now we can call the modal from our application pages.
The only actual page of our application will launch the modal dialog. This page will have a TypeScript and HTML file as well, but they already exist within our project.
Open the project’s app/app.component.ts file and include the following TypeScript code:
import { Component, ViewContainerRef } from "@angular/core";
import { ModalDialogService } from "nativescript-angular/directives/dialogs";
import { ModalComponent } from "./app.modal";
@Component({
selector: "my-app",
templateUrl: "app.component.html",
})
export class AppComponent {
public constructor(private modal: ModalDialogService, private vcRef: ViewContainerRef) { }
public showModal() {
let options = {
context: {},
fullscreen: true,
viewContainerRef: this.vcRef
};
this.modal.showModal(ModalComponent, options).then(res => {
console.log(res);
});
}
}
In the above AppComponent
class we have a constructor
method where we inject necessary services pertaining to launching modals in NativeScript. When we decide we want to launch the modal via the showModal
method we pass in a few options and launch.
The value passed back when the modal closes will be printed to the console logs.
In terms of the page UI, open the project’s app/app.component.html file and include the following XML markup:
<ActionBar title="{N} Modal Example"></ActionBar>
<StackLayout horizontalAlignment="center" verticalAlignment="center">
<Button text="Show Modal" (tap)="showModal()" class="btn btn-primary"></Button>
</StackLayout>
In the above markup we have a navigation bar and a single button centered in the screen. When the button is tapped, the showModal
method is triggered.
You just saw how to use modals in a NativeScript application. In certain scenarios it can act as an alternative to the Angular Router. These modals are popup dialogs that can have any kind of content in them, not limited to inputs and buttons. If you wish to see how to use multiple page navigation, check out the Angular Router tutorial I had written on the subject.
A video version of this article can be seen below.