Sitemap

NativeScript aka {N} Angular Modals

3 min readJul 11, 2025

--

Overview

This tutorial will guide you through mastering modals using the updated NativeDialogService in NativeScript with Angular. We’ll explore data passing, modal control, best practices, and pitfalls to avoid.

Get Sean Kelly’s stories in your inbox

Join Medium for free to get updates from this writer.

For additional resources, see:

Press enter or click to view image in full size
Mastering and Controlling Modals in NativeScript

Why Was ModalDialogService Replaced?

The old ModalDialogService was replaced starting from Angular 12 with a more rebust, modern and flexible NativeDialogService. This new service is inspired by Angular Material’s MatDialog, providing better integreation and control across platforms.

The Modal Parent Component

In NativeScript, while the developer works primarily in JavaScript and TypeScript, the code ultimately interacts with native mobile components. Let’s explore how data passes between parent components and modals when using Angular.

import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, NO_ERRORS_SCHEMA } from '@angular/core';
import { NativeDialogConfig, NativeDialog, NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular';
import { PresidentModalComponent } from '../modals/president-modal/president-modal.component';
import { PresidentModel } from '../interfaces/president-model';

@Component({
selector: 'president',
templateUrl: './president.component.html',
styleUrls: ['./president.component.scss', '../app.component.scss'],
imports: [NativeScriptCommonModule, NativeScriptRouterModule],
schemas: [NO_ERRORS_SCHEMA],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class PresidentComponent {

@Input() president: PresidentModel;

constructor(
private readonly modal: NativeDialog,
private readonly changeDetectorRef: ChangeDetectorRef
) {}

openModal(): void {
const modalOptions: NativeDialogConfig = {
data: this.president,
nativeOptions: {
fullscreen: false,
animated: false,
ios: {
presentationStyle: UIModalPresentationStyle.Custom
}
}
};
const ref = this.modal.open(PresidentModalComponent, modalOptions);

ref.afterClosed().subscribe( (isSeen: boolean) => {
this.president.isSeen = isSeen;
this.changeDetectorRef.markForCheck();
});
}}

In the majority of cases, when using the NativeDialog service two functions are used. Those being .open and .afterClosed(), an example of both can be seen in the Angular component code above.
The class NativeDialogConfig is developed from Angular Materials’s MatDialog and functions effectively as an interface for structuring a model for how the modal should look and behave in both iOS and Android.

Important Considerations

Data Passing: To reliably pass data into modal, avoid using route parameters ( ActivatedRoute ) due to inconsistent behaviour and memory management issues. Instead use:

  • Injecting data directly: inject(NATIVE_DIALOG_DATA)
  • Shared service files
  • Presentation styles on iOS
  • Native Options: For consistent modal appearance across iOS and Android, explicity set options of fullscreen and animated to false

For iOS, typically using presentationStyle: UIModalPresentationStyle.OverCurrentContext is sufficient. For presentationStyle, the enum selection goes from -2 to 8 and you can ctrl click or command click to see the full list.

declare const enum UIModalPresentationStyle {

FullScreen = 0,
PageSheet = 1,
FormSheet = 2,
CurrentContext = 3,
Custom = 4,
OverFullScreen = 5,
OverCurrentContext = 6,
Popover = 7,
BlurOverFullScreen = 8,
None = -1,
Automatic = -2
}

Using .afterClosed() enables you to handle data returned from the modal. With Angular’s OnPush change detection, manually trigger updates using markForCheck() or detectChanges().

The Modal Component

Here is how the modal itself might look:

import { ChangeDetectionStrategy, Component, ElementRef, inject, NO_ERRORS_SCHEMA, ViewChild } from '@angular/core';
import { NATIVE_DIALOG_DATA, NativeDialogRef, NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular';
import { GridLayout } from '@nativescript/core';
import { isIOS } from "@nativescript/core/platform";
import { PresidentModel } from '~/app/interfaces/president-model';

@Component({
selector: 'president-modal',
templateUrl: './president-modal.component.html',
styleUrls: ['./president-modal.component.scss', '../../app.component.scss'],
imports: [NativeScriptCommonModule, NativeScriptRouterModule],
schemas: [NO_ERRORS_SCHEMA],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class PresidentModalComponent {

dialogRef = inject(NativeDialogRef);
president = <PresidentModel>inject(NATIVE_DIALOG_DATA);
isIos: boolean = false;

constructor() {
if(isIOS) {
this.isIos = true;
}
}

close(): void {
this.dialogRef.close(true);
}

containerRef: GridLayout;
@ViewChild("container") set containerContent (elRef: ElementRef) {
if(elRef) {
this.containerRef = <GridLayout>elRef.nativeElement;
setTimeout( () => {
this.containerRef.animate({
opacity: 1,
duration: 350,
curve: 'easeIn'
});
}, 100);
}
}

}

Explanation:

  • NativeDialogRef references the dialog modal in use, providing control over the modal lifecycle and data transfers.
  • Injecting NATIVE_DIALOG_DATA ensures reliable data receipt
  • The animation used within the @ViewChild setter provides a smooth blendinging into appearance animation. This can be changes to whatever style of appearance animations you wish to create.

Alternative Approach

Another simpler method is to manually create modals using child components and boolean flags to toggle their visibility, overlaying them using a z-index higher than the parent within a *ngIfGridLayout.

  • Uses standard Angular component logic (*ngIf)
  • A backup for the possibility there is an issue with using NativeDialogService

Best Practices

  • Reliable Data Handling: Prefer direct injection over route parameters
  • Explicit Native Options: Define all options explicity for consistency
  • Manual Change Detection: Manage UI updates explicitly when using OnPush

Conclusion

The NativeDialogService in NativeScript Angular provides robust, cross-platform modal capabilities. By following this structured approach, you’ll create reliable modals with consistent behaviour across Android and iOS.

Thank you for reading!

--

--

Sean Kelly
Sean Kelly

Full Stack programmer with over 5 years of experience, using mainly Angular, NativeScript and Spring Boot.