issue rendering two dialogs on the same page.
renatodeleao opened this issue · comments
Thanks for the wrapper, i'm fan of the original plugin, and will be of this wrapper for sure :)
This sounds like a dumb question (and probably is), but i want to render [2..n]
dialogs in one page. For demo purposes i went with 2, and currently it's only rendering the last one. For the first i'm getting the following error for the first :
DOMException: Failed to execute 'showModal' on 'HTMLDialogElement': The element is not in a Document.
Demo link
My suspicions go to the portal-target
. Since we're using the "html" version of it i suspect we don't get the multiple
option that comes with the component version <portal-target multiple>
, but i might be wrong, so I wanted to get your input on this.
Thanks for your time! ✋
Hey @renatodeleao! Thanks for pointing this out, I am aware of that issue as well. I believe this is fixed with an upcoming version of PortalVue and I am kinda waiting for that update to be honest. If this issue isn't resolved any time soon, I will have to either put a warning in the README or suggest solutions.
In one of my projects, I've overcome this problem (here and here) by wrapping vue-a11y-dialog
in another component which uses again <portal>
s to place content. By that I am able to use multiple dialogs in one screen, while technically only using one dialog. I am happy to elaborate on my solution if that helps :)
that's a clever trick, thanks for sharing!
I've saw the issue on PortalVue, i'll keep an eye on it as well!
Cheers!
But i'm curious, is there a particular reason why you've chosen :target-el
over :to
prop?
vue-a11y-dialog/src/A11yDialog.vue
Line 2 in 454d177
Both are dynamic and could be opt-in. Pseudo-code:
<portal v-bind="destination" >
....
props: ['renderMode'],
computed: {
destination() {
return this.renderMode === "outside"
? {"target-el": this.portalTarget }
: {"to" : this.portalTarget }
}
}
target-el
is the API referenced for rendering a portal outside a Vue app.
I see, but as Linus has pointed target-el
is "half-assed implementation" so i was just wondering if there was any special reason behind this choice. (I know he's improving it for v2.0)
Personally haven't found any styling/accessibility issues rendering portals inside the app, I just have an extra wrapper for content where the accessibility attributes can be toggled.
<!--App.vue-->
<template>
<div id="app">
<div id="wrapper" aria-attributes>
<router-view />
</div>
<!-- portal targets -->
<portal-target name="destination1" />
<portal-target name="destination2" />
</div>
<template>
But as i've said, i was just curious, thanks you for your time man!
Up to this current release, vue-a11y-dialog
was rendered inside the app without the help of PortalVue. However, this turned out to essentially break the entire premise of a11y as the #app
container, in which the dialog is a children, will be hidden
.
I am not happy with a few implementation details as well, but eagerly waiting for the upcoming PortalVue release to (hopefully) get rid of them. For target-el
, I simply followed the API documentation and stuck with it since it's going to stay and soon to be refactored majorly.
But as i've said, i was just curious, thanks you for your time man!
No worrries, always happy to answer any questions :)
That's is correct, but the second argument of A11yDialog
constructor is an option to specify who is the content container (by default the siblings of dialog).
You already provide a prop to specify this element appRoot
, and it isn't required to be "#app". This combined with a simple computedProp renderMode
would allow you to optionally use the <portal-target>
or target-el
without any accessibility issue.
Here's your documentation example re-written to encapsulate all the thoughts of this thread
<template>
<div id="app">
<main id="content-wrapper-for-accessiblity">
<!-- ... in real world, this would be router-view -->
<button type="button" @click="openDialog">
Open dialog
</button>
<a11y-dialog
id="app-dialog"
app-root="#content-wrapper-for-accessiblity"
@dialog-ref="assignDialogRef"
portal-target="my-dialogs"
render-mode="fake-inside-prop"
>
<h1 slot="title">Your dialog title</h1>
<div>
<p>Your content</p>
</div>
</a11y-dialog>
</main>
<portal-target name="my-dialogs" multiple />
</div>
</template>
Now this is just an alternative, a cheap one in terms of code. I know that with vue-portal 2.0
fortunately these will be problems of the past.
Sorry if i'm being annoying, i'm just a nerd and can't avoid a good positive discussion around code 😄
Hey @renatodeleao, just wanted to give you a quick update that PortalVue@2 is out and the newly introduced MountingPortal
fixes the issue! I have a new release coming up either today or tomorrow. Then you will be able to use multiple portals as in your initial demo.
I've just released a new version, do you mind checking if it works for you?
@morkro works like charm, I'll leave here the updated demo for reference.
Thanks!