Skip to content

Can't open modal within modal due to ViewHierarchy error on IOS. #612

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rnmhdn opened this issue Mar 22, 2020 · 12 comments · Fixed by raphagoo/runningManApplication#13
Closed

Comments

@rnmhdn
Copy link

rnmhdn commented Mar 22, 2020

Version

2.5.0

Reproduction link

https://play.nativescript.org/?template=play-vue&id=mQF8k3&v=3

Platform and OS info

Android 8 / nativescript 6.5 / 5.4.15-arch1-1

Steps to reproduce

  • Click on Button (A modal should pop up)
  • Click on Button (Nothing will happen and you will get an error

What is expected?

You should see a new popup open.

What is actually happening?

You get the error:

ViewHierarchy: parent is already presenting view controller close the current modal page before showing another one!


Closing modal 1 and openning modal 2 / using navigation are not viable workarounds for this issue if what you intend for the user is to see modal 1 when they close modal 2 and

  • you are have multiple navigations in both modal 1 and modal 2
  • you use a custom modal component that has a close button etc and handles closure in certain ways.
  • some of your modals return dynamic values upon their closure
  • you have hooks to run on modal's closure for both modal 1 and modal 2
  • you report closure of modal 1 to server for usage analysis.
  • many other things that other people might do but I'm not doing in my app.

Please see this issue in nativescript repository.
Please see this stackoverflow question.

@rigor789
Copy link
Member

Likely related to this change: #558

To confirm, can you manually change the $showModal method in node_modules/nativescript-vue@2.5.0/dist/index.js:14165 to call

this$1.$el.nativeView...

instead of $root.

@drewjbartlett
Copy link
Contributor

Yeah, I'm having this same issue after updating to this version.

@ethnovode
Copy link

Thanks Rigor, this fix is working for me!

Likely related to this change: #558

To confirm, can you manually change the $showModal method in node_modules/nativescript-vue@2.5.0/dist/index.js:14165 to call

this$1.$el.nativeView...

instead of $root.

@rigor789
Copy link
Member

Good to know. However I'm a little unsure what to do about it - if we revert the change, we break the other now fixed issue, if we keep it this way - we introduce this limitation. 🙄

@drewjbartlett
Copy link
Contributor

What issues have you fixed with this @rigor789

@rigor789
Copy link
Member

@drewjbartlett #536

@rigor789
Copy link
Member

I think the best approach would be to add a new target option to $showModal that opens the modal on that specific element. It could either accept a vue component target: this or an element this.$el or even a nativeView.

import Modal from "./Modal";
this.$showModal(Modal, {
 fullscreen: true,
 target: this
})

@drewjbartlett
Copy link
Contributor

I think that'd be great! I'm happy to help contribute if you need the help. @rigor789

@rigor789
Copy link
Member

@drewjbartlett if you want to, sure submit a PR - I'll get it merged/released.

What I'm thinking is adding the target to the options object here:

options = Object.assign({}, options, {
context: null,
closeCallback: closeCb
})

and setting it to this.$root by default but allow overriding by user. To do that, we would add the target to the first empty object in Object.assign - {} and then change the this.$root to options.target

this.$root.nativeView.showModal(modalPage, options)

That would be the rough approach - I would like to allow passing in a Vue component instance, an element, or a nativeView. A similar thing was done for the frame option in the $navigateTo methods:

export function getFrameInstance(frame) {
// get the frame that we need to navigate
// this can be a frame id (String)
// a Vue ref to a frame
// a Frame ViewNode
// or a Frame instance
if (isObject(frame) && isDef(frame.$el)) {
frame = frame.$el.nativeView
} else if (isPrimitive(frame)) {
frame = require('@nativescript/core/ui/frame').Frame.getFrameById(frame)
} else if (isDef(frame.nativeView)) {
frame = frame.nativeView
}
// finally get the component instance for this frame
return getFrame(frame.id)
}

@romandrahan
Copy link

Same for me

@drewjbartlett
Copy link
Contributor

drewjbartlett commented Mar 24, 2020

@rigor789 - I have a working fix, however there doesn't seem to be a clear way to test this in the contributing guides. Maybe we can chat about that on my PR? I'll open shortly.

@nativescript-vue-bot
Copy link
Collaborator

We are locking this issue because it has been closed for more than 14 days.

If the issue comes up again please open a new issue with additional details.

@nativescript-vue nativescript-vue locked as resolved and limited conversation to collaborators Apr 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

Successfully merging a pull request may close this issue.

6 participants