You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a problem? Please describe.
Not yet but may create a problem for it (likely related to several other reported issues in all sorts of subtle ways).
Describe the solution you'd like
Right now in order to open a modal you must pass the proper ViewContainerRef. This is simply error prone, not versatile and frustrating for sophisticated app development at scale.
Describe alternatives you've considered
Keeping track of the current ViewContainerRef via a service. This works in a majority of cases but due to race conditions and various asynchronous contexts this has been found to be not reliable. Simply put: requiring developers to use a ViewContainerRef to simply open a modal is highly frustrating.
Additional context
I haven't investigated refactoring modal handling just yet but plan to. There must be a way to handle modals without dealing with ViewContainerRef at all or rather the framework could open modals in the right context all the time without leaving it up for the developer to keep track of it since it has been found to be so error prone.
@NathanWalker The ability to pass different ViewContainerRef instances when opening a modal is very important when you want to have navigation inside the modal view. This navigation must be declared in your route config at a certain level. This must match the level of the ViewContainerRef, so that these paths are correctly matched by the router.
We all agree that opening a modal right now brings with itself a lot of boilerplate code that is not really needed. At the same time we want to provide openness to the API, so that a lot of modal and navigation patterns are supported. Perhaps we should rethink this approach and provide different APIs for the different scenarios.
That being said, the error you get "ViewHierarchy: Parent page is not part of the window hierarchy. Close the current modal page before showing another one!" means that you are passing a ViewContainerRef that is not loaded in your app at this time. It looks like something connected to opening/closing modal views, but you haven't shared the case. Can you share a scenario where you achieved this?
This navigation must be declared in your route config at a certain level. This must match the level of the ViewContainerRef, so that these paths are correctly matched by the router.
Does this mean that if I have the following configuration:
the modal presents correctly and the ModalInitiatorComponent does not get destroyed despite the ModalComponent being outside of the ModalInitiatorComponent tree? I've been using Angular's named router outlets to overcome this - and avoid patching the routes at runtime - but there's no page animation between modal pages, which the regular routed modals have - when their routes are children of the component that shows the modal.
The most common use case I see for this is a login modal which has registration and password recovery as accessory pages. You'd want for the modal to be able to display all of these and hence setup routing.
@tiagoblackcode The component that you pass to the showModal() function is the root of the modal view. It gets created dynamically and shown as a modal. There is no need to declare it in the Angular routes config. If you want to have navigation inside this modal view, you have to set this modal component`s root as a page-router-outlet (like you did), declare the routes that will be navigated there, and navigate to them. See the example in the docs - https://docs.nativescript.org/angular/ui/modal-view-ng#modal-view-navigation.
Yes, I understand that. The Routes configuration above has an extra route for the ModalComponent which hosts the page-router-outlet, my bad.
However, what I was trying to ask was if the modal routes (ModalChildComponent in the example above) can be outside of the route tree of the caller component (`ModalInitiatorComponent in the example above).
IIRC the issue I encountered if the modal routes were not under the caller tree was that when the modal was opened, the underlying page was destroyed and when the modal closed there was a blank page.
And that's what I've been doing. However, you lose two features: 1) animations between modal page transitions; 2) the ability to pass query parameters around. The 2nd one is not that important but the first one has some impact in the user experience IMHO.
With this configuration, the "root" route has the outlet declaration while the child routes don't. While the modals work just fine, the animations don't.
Later, I tried eager loading the routes still nested under a "root" route similar to the above, but with the children entry instead of the loadChildren entry, and still without declaring the outlet in the child routes. The modals work but there are no animations neither RouterExtensions#backToPreviousPage does work (link: https://play.nativescript.org/?template=play-ng&id=E6WyBS&v=28).
@tiagoblackcode The issues you reported are known. They all boil down to nesting named/aux outlets. There is a PR that should fix them - #1556.
The issue with lazy loading aux/named outlets is a curios one. The reason why you don't have animations is because Angular is injecting a basic router-outlet in this case. This outlet doesn't have a page, action bar or transitions. The PR will allow a workaround for that.
Makes sense it doesn't work like that. I didn't know Angular added a router-outlet in that case. It must do that to handle both children and loadChildren since the behaviour is consistent.
I have a fix for error "ViewHierarchy: Parent page is not part of the window hierarchy." with no previous modal open - just warp your showModal line with a setTimeout. Here's a working example.
setTimeout(()=>{view.showModal('path-to-your-modal',optionsShow)// WATCHOUT - no error if page doesn't exist and no modal will open},0)
Activity
[-]feat: easier ViewContainerRef handling with modals[/-][+]feat(modals): easier ViewContainerRef handling[/+]NathanWalker commentedon Oct 8, 2018
This is the dreaded error that occurs on iOS:
Which means your app is now dead and you can no longer open modals at all and in most cases you can't use the app anymore.
NathanWalker commentedon Oct 8, 2018
These are the "white screens of death" that apps can result in:

NathanWalker commentedon Oct 8, 2018
Fundamentally I think part of the issue is in core modules and could be an iOS race condition:
https://stackoverflow.com/a/7194182
Likely need more fine grain control of modal presenting and dismissing to ensure none overlap in here:
https://github.com/NativeScript/NativeScript/blob/master/tns-core-modules/ui/core/view/view.ios.ts#L429
and when dealing with this logic:
https://github.com/NativeScript/NativeScript/blob/master/tns-core-modules/ui/core/view/view.ios.ts#L366-L377 which is ultimately buggy due to some race condition here.
MartoYankov commentedon Oct 9, 2018
@NathanWalker The ability to pass different
ViewContainerRefinstances when opening a modal is very important when you want to have navigation inside the modal view. This navigation must be declared in your route config at a certain level. This must match the level of theViewContainerRef, so that these paths are correctly matched by the router.We all agree that opening a modal right now brings with itself a lot of boilerplate code that is not really needed. At the same time we want to provide openness to the API, so that a lot of modal and navigation patterns are supported. Perhaps we should rethink this approach and provide different APIs for the different scenarios.
That being said, the error you get "ViewHierarchy: Parent page is not part of the window hierarchy. Close the current modal page before showing another one!" means that you are passing a
ViewContainerRefthat is not loaded in your app at this time. It looks like something connected to opening/closing modal views, but you haven't shared the case. Can you share a scenario where you achieved this?NathanWalker commentedon Oct 9, 2018
See comments in the PR @MartoYankov thanks for investigating with me 👍
tiagoblackcode commentedon Oct 15, 2018
@MartoYankov
Does this mean that if I have the following configuration:
the modal presents correctly and the
ModalInitiatorComponentdoes not get destroyed despite theModalComponentbeing outside of theModalInitiatorComponenttree? I've been using Angular's named router outlets to overcome this - and avoid patching the routes at runtime - but there's no page animation between modal pages, which the regular routed modals have - when their routes are children of the component that shows the modal.The most common use case I see for this is a login modal which has registration and password recovery as accessory pages. You'd want for the modal to be able to display all of these and hence setup routing.
MartoYankov commentedon Oct 15, 2018
@tiagoblackcode The component that you pass to the
showModal()function is the root of the modal view. It gets created dynamically and shown as a modal. There is no need to declare it in the Angular routes config. If you want to have navigation inside this modal view, you have to set this modal component`s root as a page-router-outlet (like you did), declare the routes that will be navigated there, and navigate to them. See the example in the docs - https://docs.nativescript.org/angular/ui/modal-view-ng#modal-view-navigation.tiagoblackcode commentedon Oct 15, 2018
Yes, I understand that. The
Routesconfiguration above has an extra route for theModalComponentwhich hosts thepage-router-outlet, my bad.However, what I was trying to ask was if the modal routes (
ModalChildComponentin the example above) can be outside of the route tree of the caller component (`ModalInitiatorComponent in the example above).IIRC the issue I encountered if the modal routes were not under the caller tree was that when the modal was opened, the underlying page was destroyed and when the modal closed there was a blank page.
MartoYankov commentedon Oct 15, 2018
@tiagoblackcode To achieve this you must use angular's named/aux router outlet concept. See this playground example - https://play.nativescript.org/?template=play-ng&id=E6WyBS&v=2.
tiagoblackcode commentedon Oct 16, 2018
And that's what I've been doing. However, you lose two features: 1) animations between modal page transitions; 2) the ability to pass query parameters around. The 2nd one is not that important but the first one has some impact in the user experience IMHO.
MartoYankov commentedon Oct 16, 2018
@tiagoblackcode You can navigate between pages in the modal view and there are transitions. I've updated the playground with a navigation inside the modal. See https://play.nativescript.org/?template=play-ng&id=E6WyBS&v=2 .
tiagoblackcode commentedon Oct 16, 2018
@MartoYankov can confirm the animations are working in the playground. I've updated the playground with the navigation within modals: https://play.nativescript.org/?template=play-ng&id=E6WyBS&v=9 . I'm going to double-check what's happening in the project I'm working.
Thank you very much for taking the time.
tiagoblackcode commentedon Oct 17, 2018
@MartoYankov
So, in my previous configuration I had modal pages lazy-loaded with the following configuration:
With this configuration, the "root" route has the outlet declaration while the child routes don't. While the modals work just fine, the animations don't.
Later, I tried eager loading the routes still nested under a "root" route similar to the above, but with the
childrenentry instead of theloadChildrenentry, and still without declaring theoutletin the child routes. The modals work but there are no animations neitherRouterExtensions#backToPreviousPagedoes work (link: https://play.nativescript.org/?template=play-ng&id=E6WyBS&v=28).e.g.
Lastly, I've added the
outletto the child routes and this time the modals do not work.So, in conclusion:
Edit: updated a use case
Kind Regards,
Tiago Melo
MartoYankov commentedon Oct 17, 2018
@tiagoblackcode The issues you reported are known. They all boil down to nesting named/aux outlets. There is a PR that should fix them - #1556.
The issue with lazy loading aux/named outlets is a curios one. The reason why you don't have animations is because Angular is injecting a basic router-outlet in this case. This outlet doesn't have a page, action bar or transitions. The PR will allow a workaround for that.
tiagoblackcode commentedon Oct 17, 2018
Makes sense it doesn't work like that. I didn't know Angular added a
router-outletin that case. It must do that to handle bothchildrenandloadChildrensince the behaviour is consistent.Nice one! Gonna see if I can test it :)
flipperlite commentedon Mar 15, 2024
I have a fix for error "ViewHierarchy: Parent page is not part of the window hierarchy." with no previous modal open - just warp your showModal line with a setTimeout. Here's a working example.