_ NativeScriptのModal View内で画面遷移する際にcontextを渡す
NativeScriptのModal View内で画面遷移する場合、Frameを作ってその中にModal Viewを展開する必要がありますが、公式ドキュメント通りだとcontextが渡りません。
_ 公式ドキュメント方式
main-page.js
1
2
3
| | const mainpage = args.object.page;
const context = "some context";
mainpage.showModal("modal-root", context, () => {}, true);
|
modal-root.xml
1
| <Frame defaultPage="first-modal-view-page">
|
first-modal-view-page.xml
1
2
3
4
5
6
| <Page backgroundColor="green" navigatingTo="onNavigatingTo">
<StackLayout backgroundColor="lightGreen">
<Button text="Navigate" tap="onNavigate"/>
<Button text="Close Modal" tap="onCloseModal"/>
</StackLayout>
</Page>
|
first-modal-view-page.js
1
2
3
4
| | function onNavigatingTo(args) {
console.log(args.context); }
exports.onNavigate = onNavigate;
|
_ 解決方法
そこで、参考ページの通り、frameを作ってあげてその中のshownModallyイベントからさらにcontextを渡すようにします。
main-page.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| | const Frame = require("tns-core-modules/ui/frame").Frame;
function onTap(args){
const frame = new Frame();
frame.on("shownModally",(args)=>{
const component = args.object;
if(!component.isLayoutValid){ frame.navigate({
moduleName: "first-modal-view-page",
context: args.context });
}
});
const page = args.object.page;
const context = "some context";
page.showModal(frame, context, () => {}, true);
}
|
modal-root.xmlは不要です。
これでModal Viewの中でnavigateできますし、ActionBarも効くようになりました。
_ 2019/4/23追記
参考ページのままだと、HOMEボタンで一旦アプリを閉じた後再表示させた再に再度Navigateしてしまい、backボタンを押しても再度同じ画面が表示される(二重に画面遷移している)事が分かりました。このため、再表示時はnavigateしないよう、7行目のif文を追加しました。
但し、このisLayoutValidの役割についてはいまいちはっきりしていません。それぞれの操作をした際のプロパティの違いを元に実装していますので、場合によっては期待通り動いてくれない事があるかもしれません。
_ Modalダイアログの戻り値を受け取る(2019/5/6追記)
Modalを閉じた際、Modal内で処理した結果を受け取る方法です。
公式ドキュメント通りcloseCallbackを使いますが、Modal内の遷移先まで渡す必要があります。
まず、呼び出し側では、callback関数に受け取る引数を指定する(14行目)のと、遷移先のページにcontextとしてcloseCallbackを渡します(
7行目)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
-
|
-
|
-
|
|
!
!
!
-
|
!
| const component = args.object;
const page = component.page;
const frame = new Frame();
frame.on("shownModally",(args)=>{
const component = args.object;
if(!component.isLayoutValid){ args.context.closeCallback = args.closeCallback;
frame.navigate({
moduleName: "reserve/reserve-cancel/reserve-cancel-page",
context: args.context
});
}
});
page.showModal(frame, context, (result) => {
console.log('result='+result);
}, true);
|
次にModal側では、クラス変数にcloseCallbackを保存しておき(1,4行目)closeModal()の代わりにcloseCallback()を呼び出し、引数に返り値を渡します(11行目)。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
|
|
!
-
|
|
!
| let closeCallback;
function onNavigatingTo(args) {
closeCallback = args.context.closeCallback;
:
}
exports.onNavigatingTo = onNavigatingTo;
function onCloseButtonTap(args) {
const component = args.object;
closeCallback("返り値");
}
exports.onCloseButtonTap= onCloseButtonTap;
|
これで、Modalを閉じた際にconsoleにresult=返り値が表示されればOKです。