NativeScript Core

Modal View Ng

Modal Dialog

The following example is demonstrating how to create a modal page with ActionBar. The main-view.component is the page from which, you will open the root modal (modal-root.component). The root modal contains a page-router-outlet and has a default navigation to modal-view.component while using the children routing configuration.

main-view.component.html and main-view.component.ts

<!-- main-view.component.html -->
<StackLayout class="page" sdkExampleTitle sdkToggleNavButton>
    <Button text="SHOW MODAL" (tap)="onTap()"></Button>
</StackLayout>
// main-view.component.ts
import { Component, OnInit, ViewContainerRef } from "@angular/core";
import { ModalDialogOptions, ModalDialogService } from "nativescript-angular/modal-dialog";
import { ModalRootComponent } from "./modal-root.component";

@Component({
    moduleId: module.id,
    providers: [ModalDialogService],
    templateUrl: "./main-view.component.html"
})
export class MainViewComponent implements OnInit {
    constructor(
        private _modalService: ModalDialogService,
        private _vcRef: ViewContainerRef) { }

    ngOnInit(): void { }

    onTap(): void {
        const options: ModalDialogOptions = {
            viewContainerRef: this._vcRef,
            context: {},
            fullscreen: true
        };

        this._modalService.showModal(ModalRootComponent, options)
            .then((result: string) => {
                console.log(result);
            });
    }
}

Routing configuration file (modal-view-examples.module.ts) which sets the children routes (in this example the modal-view path).

{
    path: "modal-view-actionbar",
    component: MainViewComponent,
    data: { title: "Main page" },
    children: [
        {
            path: "modal-view", component: ModalViewActionBarComponent
        }
    ]
}

modal-root.component.html and modal-root.component.ts contains page-router-outlet with default navigation via modal-view path.

<page-router-outlet></page-router-outlet>
import { Component, OnInit } from "@angular/core";
import { RouterExtensions } from "nativescript-angular/router";
import { ActivatedRoute } from "@angular/router";

@Component({
    moduleId: module.id,
    templateUrl: "./modal-root.component.html"
})
export class ModalRootComponent implements OnInit {
    constructor(
        private _routerExtensions: RouterExtensions,
        private _activeRoute: ActivatedRoute) {}

    ngOnInit(): void {
        this._routerExtensions.navigate(["modal-view"], { relativeTo: this._activeRoute });
    }
}

modal-view.component.html and modal-view.component.ts (the default modal-view path). The modal contains ActionBar.

<ActionBar backgroundColor="red" title="MODAL VIEW" class="action-bar">
</ActionBar>

<StackLayout backgroundColor="green" class="page">
    <Label class="my-label" style="text-align: center;" text="Modal view with ActionBar" textWrap="true"></Label>
    <Button text="CLOSE MODAL" (tap)="onClose()"></Button>
</StackLayout>
import { Component, OnInit } from "@angular/core";
import { RouterExtensions } from "nativescript-angular/router";
import { ActivatedRoute } from "@angular/router";
import { ModalDialogParams } from "nativescript-angular/modal-dialog";
import { Page } from "tns-core-modules/ui/page";

@Component({
    moduleId: module.id,
    templateUrl: "./modal-view.component.html",
    styleUrls: ["./modal-view.component.css"]
})
export class ModalViewActionBarComponent implements OnInit {
    constructor(private _params: ModalDialogParams, private _page: Page, private router: RouterExtensions, private _activeRoute: ActivatedRoute) {}

    ngOnInit(): void {}
    onClose(): void {
        this._params.closeCallback("return value");
    }
}

Improve this document

Demo Source


The following example demonstrates how to enable navigaiton within a modal page. First we have a component which opens the main root modal. The root modal contains a page-router-outlet which has a default navigaiton via the modal route (loads the home-modal-view-content.component). The router outlet has its own routing table (modal-view-examples.module.ts) and can navigate to the second-modal route within the root modal.

Providing the ModalDialogService in @NgModule config. app.module.ts

// this import should be first in order to load some required settings (like globals and reflect-metadata)
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { NativeScriptFormsModule } from "nativescript-angular/forms";
import { routes } from "./app.routes";
import { AppComponent } from "./app.component";
import { ModalDialogService } from "nativescript-angular/modal-dialog";

@NgModule({
    schemas: [NO_ERRORS_SCHEMA],
    declarations: [
        AppComponent,
    ],
    bootstrap: [AppComponent],
    imports: [
        NativeScriptModule,
        NativeScriptFormsModule,
        NativeScriptRouterModule,
        NativeScriptRouterModule.forRoot(routes),
    ],
    providers: [
        ModalDialogService,
    ]
})

export class AppModule { }

The component (modal-view-navigation.component) which opens the root modal view (home-modal-view.component).

modal-view-navigation.component.html and _modal-view-navigation.component.ts

<StackLayout class="page" sdkExampleTitle sdkToggleNavButton>
    <Button text="SHOW MODAL" (tap)="onTap()"></Button>
</StackLayout>
import { Component, ViewContainerRef } from "@angular/core";
import { ModalDialogOptions, ModalDialogService } from "nativescript-angular/modal-dialog";
import { HomeModalViewComponent } from "./home-modal-view.component";

@Component({
    moduleId: module.id,
    providers: [ModalDialogService],
    templateUrl: "./modal-view-navigation.component.html"
})
export class ModalViewNavigationComponent {
    constructor(private _modalService: ModalDialogService, private _vcRef: ViewContainerRef) { }

    onTap(): void {
        const options: ModalDialogOptions = {
            viewContainerRef: this._vcRef,
            context: {},
            fullscreen: true
        };

        this._modalService.showModal(HomeModalViewComponent, options)
            .then((result: string) => {
                console.log(result);
            });
    }
}

Routing configuration file (modal-view-examples.module.ts) which sets the children routes (in this example the modal and second-modal path).

{
    path: "modal-view-navigation",
    component: ModalViewNavigationComponent,
    data: { title: "Modal view navigation" },
    children: [
        {
            path: "modal", component: HomeModalViewContentComponent
        },
        {
            path: "second-modal", component: SecondModalViewContentComponent
        }
    ]
},

The root modal component contains the page-router-outlet and has a default navigation to the first inner modal view.

home-modal-view.component.html and home-modal-view.component.ts

<page-router-outlet></page-router-outlet>
import { Component, OnInit } from "@angular/core";
import { RouterExtensions } from "nativescript-angular/router";
import { ActivatedRoute } from "@angular/router";

@Component({
    moduleId: module.id,
    templateUrl: "./home-modal-view.component.html"
})
export class HomeModalViewComponent implements OnInit {
    constructor(
        private _routerExtensions: RouterExtensions,
        private _activeRoute: ActivatedRoute) {}

    ngOnInit(): void {
        this._routerExtensions.navigate(["modal"], { relativeTo: this._activeRoute });
    }
}

Defining the first inner modal view (the modal route).

home-modal-view-content.component.html and home-modal-view-content.component.ts

<ActionBar title="MODAL VIEW" class="action-bar">
</ActionBar>

<StackLayout class="page">
    <Label class="my-label" text="First Modal View" textWrap="true"></Label>
    <Button text="Next" (tap)="onNavigate()"></Button>
    <Button text="CLOSE MODAL" (tap)="onClose()"></Button>
</StackLayout>
import { Component, OnInit } from "@angular/core";
import { RouterExtensions } from "nativescript-angular/router";
import { ActivatedRoute } from "@angular/router";
import { ModalDialogParams } from "nativescript-angular/modal-dialog";
import { Page } from "tns-core-modules/ui/page";

@Component({
    moduleId: module.id,
    templateUrl: "./home-modal-view-content.component.html",
    styleUrls: ["./home-modal-view-content.component.css"]
})
export class HomeModalViewContentComponent implements OnInit {
    constructor(private _params: ModalDialogParams, private _page: Page, private router: RouterExtensions, private _activeRoute: ActivatedRoute) {}

    ngOnInit(): void {}
    onNavigate(): void {
        this.router.navigate(["../second-modal"], { relativeTo: this._activeRoute });
    }
    onClose(): void {
        this._params.closeCallback("return value");
    }
}

Note: We can navigate to the second component inside the Modal view while defining its relative path(e.g. "../second-modal"). To navigate relatively, we should use ActiveRouter module as it is demonstrated in the example above.

Defining the first inner modal view (the second-modal route).

second-modal-view-content.component.html and second-modal-view-content.component.ts

<ActionBar title="SECOND MODAL VIEW" class="action-bar">
</ActionBar>

<StackLayout class="page">

    <Label class="my-label" text="Second Modal view" textWrap="true"></Label>
    <Button text="Go Back" (tap)="onBack()"></Button>
    <Button text="CLOSE MODAL" (tap)="onClose()"></Button>
</StackLayout>
import { Component } from "@angular/core";
import { RouterExtensions } from "nativescript-angular/router";
import { ModalDialogParams } from "nativescript-angular/modal-dialog";

@Component({
    moduleId: module.id,
    templateUrl: "./second-modal-view-content.component.html",
    styleUrls: ["./second-modal-view-content.component.css"]
})
export class SecondModalViewContentComponent  {
    constructor(private _params: ModalDialogParams, private router: RouterExtensions) { }

    onBack(): void {
        this.router.back();
    }
    onClose(): void {
        this._params.closeCallback("return value");
    }
}

Improve this document

Demo Source


Sample Modal View Module Example

Modal Dialog

app.module.ts

// this import should be first in order to load some required settings (like globals and reflect-metadata)
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { NativeScriptFormsModule } from "nativescript-angular/forms";
import { routes } from "./app.routes";
import { AppComponent } from "./app.component";
import { ModalDialogService } from "nativescript-angular/modal-dialog";

@NgModule({
    schemas: [NO_ERRORS_SCHEMA],
    declarations: [
        AppComponent,
    ],
    bootstrap: [AppComponent],
    imports: [
        NativeScriptModule,
        NativeScriptFormsModule,
        NativeScriptRouterModule,
        NativeScriptRouterModule.forRoot(routes),
    ],
    providers: [
        ModalDialogService,
    ]
})

export class AppModule { }

The host component (sample-modal-view-module.example.html) from which we will open the different modal pages (e.g., modal-view.html).

sample-modal-view-module.example.html

<ScrollView sdkExampleTitle sdkToggleNavButton >
    <StackLayout>
        <Label text='Count the days between the dates' class="m-15 h2" textWrap="true"></Label>

        <Label [text]='startDate | date:"MM/dd/yy"' class="m-15" textWrap="true"></Label>  
        <Button class="btn btn-primary btn-active" text="Enter Start Date" (tap)="getStartDate()"></Button>

        <Label [text]='endDate | date:"MM/dd/yy"' class="m-15" textWrap="true"></Label>   
        <Button class="btn btn-primary btn-active" text="Enter End Date" (tap)="getEndDate()"></Button>

        <Label [text]='"Days: " + days' class="m-15" textWrap="true"></Label> 
        <Button class="btn btn-primary btn-active" text="Count Days" (tap)="countDays()"></Button>

        <Label text='Use different date formats' class="m-15 h2" textWrap="true"></Label>

        <Label [text]='"Date: " + (selectedDate | date: "MM/dd/yy")' class="m-15" textWrap="true"></Label>
        <Label [text]='"Weekday: " + (selectedDate | date: "EEEE")' class="m-15" textWrap="true"></Label>
        <Button class="btn btn-primary btn-active" text="Enter Date" (tap)="getDate()"></Button>   
    </StackLayout>
</ScrollView>

Passing parameters from the opened modal view.

modal-view.html and modal-view.ts

<StackLayout class="modal-view-style" sdkExampleTitle sdkToggleNavButton>
    <DatePicker #datepicker></DatePicker>
    <Button class="btn btn-primary btn-active" text="Submit" (tap)="submit()"></Button>
</StackLayout>
import { Component, OnInit, ViewChild, ElementRef } from "@angular/core";
import { ModalDialogParams } from "nativescript-angular/modal-dialog";
import { DatePicker } from "tns-core-modules/ui/date-picker";

@Component({
    moduleId: module.id,
    templateUrl: "./modal-view.html",
})
export class ModalViewComponent implements OnInit {
    public currentdate: Date;
    @ViewChild("datepicker", { read: ElementRef, static: true }) datePickerElement: ElementRef;

    constructor(private params: ModalDialogParams) {
        this.currentdate = new Date(params.context);
    }

    ngOnInit() {
        let datePicker: DatePicker = <DatePicker>this.datePickerElement.nativeElement;
        datePicker.year = this.currentdate.getFullYear();
        datePicker.month = this.currentdate.getMonth() + 1;
        datePicker.day = this.currentdate.getDate();
        datePicker.minDate = new Date(1975, 0, 29);
        datePicker.maxDate = new Date(2045, 4, 12);
    }

    public submit() {
        let datePicker: DatePicker = <DatePicker>this.datePickerElement.nativeElement;
        console.log("date result");
        console.log(datePicker.date);
        this.params.closeCallback(datePicker.date);
    }
}

Receiving the result from the modal page.

getDate() {
    this.createModelView().then(result => {
        if (this.validate(result)) {
            this.selectedDate = result;
        }
    }).catch(error => this.handleError(error));
}

private createModelView(): Promise<any> {
    const today = new Date();
    const options: ModalDialogOptions = {
        viewContainerRef: this.vcRef,
        context: today.toDateString(),
        fullscreen: false,
    };

    // showModal returns a promise with the received paramerters from the modal page
    return this.modalService.showModal(ModalViewComponent, options);
}

Improve this document

Demo Source