diff --git a/tests/app/ui/page/modal-tab-page.ts b/tests/app/ui/page/modal-tab-page.ts
new file mode 100644
index 000000000..9585789bf
--- /dev/null
+++ b/tests/app/ui/page/modal-tab-page.ts
@@ -0,0 +1,13 @@
+import { NavigatedData } from "tns-core-modules/ui/page";
+import { View } from "tns-core-modules/ui/core/view";
+import * as TKUnit from "../../TKUnit";
+import { stack } from "tns-core-modules/ui/frame";
+import { isAndroid } from "tns-core-modules/platform";
+
+export function onNavigatedTo(args: NavigatedData) {
+ TKUnit.assertEqual(stack().length, 2, "Host and tab modal frame should be instantiated at this point!");
+ // shownModally raised after page.NavigatedTo on iOS so we close modal there
+ if (isAndroid) {
+ (args.object as View).closeModal();
+ }
+}
diff --git a/tests/app/ui/page/modal-tab-page.xml b/tests/app/ui/page/modal-tab-page.xml
new file mode 100644
index 000000000..31586bea6
--- /dev/null
+++ b/tests/app/ui/page/modal-tab-page.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/tests/app/ui/page/modal-tab-root.ts b/tests/app/ui/page/modal-tab-root.ts
new file mode 100644
index 000000000..20b26a0ef
--- /dev/null
+++ b/tests/app/ui/page/modal-tab-root.ts
@@ -0,0 +1,22 @@
+import { ShownModallyData } from "tns-core-modules/ui/core/view";
+import { TabView } from "tns-core-modules/ui/tab-view/tab-view";
+import * as TKUnit from "../../TKUnit";
+import { stack } from "tns-core-modules/ui/frame";
+import { isIOS } from "tns-core-modules/platform"
+
+export function onShownModally(args: ShownModallyData) {
+ const tabView = args.object;
+ TKUnit.assertNotNull(tabView);
+ if (args.context) {
+ args.context.shownModally = true;
+ }
+
+ const hostFrame = stack()[0];
+ TKUnit.assertNotNull(hostFrame, "Host frame should not be null");
+ TKUnit.assertEqual(hostFrame.currentPage.modal, tabView, "hostFrame.currentPage.modal should be equal to the tabView instance on tabView.shownModally event handler.");
+
+ // shownModally raised after page.NavigatedTo on iOS
+ if (isIOS) {
+ args.closeCallback("return value");
+ }
+}
\ No newline at end of file
diff --git a/tests/app/ui/page/modal-tab-root.xml b/tests/app/ui/page/modal-tab-root.xml
new file mode 100644
index 000000000..9760affe7
--- /dev/null
+++ b/tests/app/ui/page/modal-tab-root.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/app/ui/page/page-tests-common.ts b/tests/app/ui/page/page-tests-common.ts
index 3e344fe6b..6efd3e5f8 100644
--- a/tests/app/ui/page/page-tests-common.ts
+++ b/tests/app/ui/page/page-tests-common.ts
@@ -23,6 +23,7 @@ import { Frame, stack } from "tns-core-modules/ui/frame";
import { Label } from "tns-core-modules/ui/label";
import { Color } from "tns-core-modules/color";
import { TabView, TabViewItem } from "tns-core-modules/ui/tab-view/tab-view";
+import { _resetRootView, getRootView } from "tns-core-modules/application";
export function addLabelToPage(page: Page, text?: string) {
const label = new Label();
@@ -874,6 +875,71 @@ export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalPage() {
TKUnit.assertTrue(shownModallyCount === 1);
}
+export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalTabView() {
+ let showingModallyCount = 0;
+ let shownModallyCount = 0;
+
+ let ready = false;
+
+ const modalCloseCallback = function (returnValue: any) {
+ TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
+
+ ready = true;
+ }
+
+ const modalTabViewShowingModallyEventHandler = function(args: ShownModallyData) {
+ showingModallyCount++;
+ }
+
+ const modalTabViewShownModallyEventHandler = function(args: ShownModallyData) {
+ shownModallyCount++;
+ }
+
+ const hostNavigatedToEventHandler = function(args) {
+ const page = args.object;
+ page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
+
+ const basePath = "ui/page/";
+ const entry: NavigationEntry = {
+ moduleName: basePath + "modal-tab-root"
+ };
+
+ TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
+
+ const modalTabView = createViewFromEntry(entry) as TabView;
+ modalTabView.on(TabView.showingModallyEvent, modalTabViewShowingModallyEventHandler);
+ modalTabView.on(TabView.shownModallyEvent, modalTabViewShownModallyEventHandler);
+
+ TKUnit.assertEqual(stack().length, 2, "Host and tab modal frame should be instantiated at this point!");
+
+ page.showModal(modalTabView, { }, modalCloseCallback, false, false);
+ }
+
+ const masterPageFactory = function (): Page {
+ const masterPage = new Page();
+ masterPage.id = "masterPage_test_WhenModalPageShownShowModalEventsRaisedOnRootModalTabView";
+ masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler);
+
+ const label = new Label();
+ label.text = "Text";
+ masterPage.content = label;
+ return masterPage;
+ };
+
+ TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
+
+ helper.navigate(masterPageFactory);
+
+ TKUnit.assertEqual(stack().length, 2, "Host and modal tab frame should be instantiated at this point!");
+
+ TKUnit.waitUntilReady(() => ready);
+
+ TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
+
+ TKUnit.assertTrue(showingModallyCount === 1);
+ TKUnit.assertTrue(shownModallyCount === 1);
+}
+
export function test_percent_width_and_height_support() {
const testPage = new Page();
testPage.id = "test_percent_width_and_height_support";
@@ -935,40 +1001,3 @@ export function test_percent_margin_support() {
TKUnit.assertEqual(bounds.right, parentWidth, "Stack RIGHT position incorrect");
TKUnit.assertEqual(bounds.bottom, parentHeight, "Stack BOTTOM position incorrect");
}
-
-//export function test_ModalPage_Layout_is_Correct() {
-// const testPage: Page;
-// const label: Label;
-// const pageFactory = function () {
-// testPage = new Page();
-// label = new Label();
-// label.text = "Will Show modal page";
-// testPage.content = label;
-// return testPage;
-// };
-
-// helper.navigate(pageFactory);
-// const basePath = "ui/page/";
-// testPage.showModal(basePath + "page21", testPage, () => { }, false);
-
-// // TODO: Remove this once navigate and showModal returns Promise.
-// TKUnit.wait(0.350);
-// const childPage = (testPage).childPage;
-// const closeCallback: Function = (testPage).close;
-
-// try {
-// const layout = childPage.content;
-// const repeater = layout.getChildAt(1);
-// TKUnit.assertTrue(repeater.isLayoutValid, "layout should be valid.");
-// const bounds = repeater._getCurrentLayoutBounds();
-// const height = bounds.bottom - bounds.top;
-// TKUnit.assertTrue(height > 0, "Layout should be >0.");
-
-// closeCallback();
-// TKUnit.wait(0.150);
-// }
-// finally {
-// helper.goBack
-// helper.goBack();
-// }
-//}
\ No newline at end of file
diff --git a/tns-core-modules/ui/core/view-base/view-base.ts b/tns-core-modules/ui/core/view-base/view-base.ts
index 7056f8051..75233bcfa 100644
--- a/tns-core-modules/ui/core/view-base/view-base.ts
+++ b/tns-core-modules/ui/core/view-base/view-base.ts
@@ -959,7 +959,10 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
}
public _dialogClosed(): void {
- return;
+ eachDescendant(this, (child: ViewBase) => {
+ child._dialogClosed();
+ return true;
+ });
}
public _onRootViewReset(): void {
diff --git a/tns-core-modules/ui/frame/frame-common.ts b/tns-core-modules/ui/frame/frame-common.ts
index aee925fa7..3b8552664 100644
--- a/tns-core-modules/ui/frame/frame-common.ts
+++ b/tns-core-modules/ui/frame/frame-common.ts
@@ -435,7 +435,8 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
}
public _dialogClosed(): void {
- this._popFromFrameStack();
+ // No super call as we do not support nested frames to clean up
+ this._removeFromFrameStack();
}
public _onRootViewReset(): void {