Reputation: 1711
I'm working on a layout where you can click on a link from the main menu and it opens a modal window that uses Alpine.js. In desktop view, this works fine.
But I've also got a second nav which is only viewable in mobile view and you have to click on a hamburger icon to open it. The link to the same modal from within the mobile menu doesn't work.
A basic version of the HTML is below. I've also created a Codepen which illustrates the problem. The link to launch the modal is assessment.
In desktop view, clicking assessment opens the modal. Doing the same from the mobile menu only closes the menu again (which is intentional as each link in the menu links to an anchor further down the page).
What do I need to do to get the modal to launch from the mobile view too?
<div
id="page"
x-data="{ 'isDialogOpen': false }"
@keydown.escape="isDialogOpen = false"
>
<header>
<div>
<nav>
<a href="#page">home</a>
<a href="#section-about">about</a>
<a href="#assessment" @click="isDialogOpen = true">assessment</a>
<a href="#section-overview">overview</a>
</nav>
<nav
x-data="{ isOpen: false, isDialogOpen: false }"
@keydown.escape="isOpen = false"
:class="{ 'fixed left-0 w-full' : isOpen , 'absolute' : !isOpen}"
>
<button
@click="isOpen = !isOpen"
type="button"
:class="{ 'transition transform-180 ml-8': isOpen }"
>
<svg>
<path x-show="isOpen"/>
<path x-show="!isOpen"/>
</svg>
</button>
<div
:class="{ 'block': isOpen, 'hidden': !isOpen }"
@click.away="isOpen = false"
x-show.transition="true"
>
<ul>
<li>
<a
href="#page"
@click="isOpen = false"
>
home
</a>
</li>
<li>
<a
href="#section-about"
@click="isOpen = false"
>
about
</a>
</li>
<li>
<a
href="#assessment"
@click="isDialogOpen = true, isOpen = false"
>
assessment
</a>
</li>
<li>
<a
href="#section-overview"
@click="isOpen = false"
>
overview
</a>
</li>
</ul>
</div>
</nav>
</div>
</header>
<div
id="assessment"
x-show="isDialogOpen"
:class="{ 'absolute inset-0 z-40 flex items-start justify-center': isDialogOpen }"
>
<div
x-show="isDialogOpen"
@click.away="isDialogOpen = false"
>
<div>
<h2>Heading</h2>
<button type="button" @click="isDialogOpen = false">✖</button>
</div>
<div>
<p>Content</p>
</div>
</div>
</div>
</div>
Upvotes: 0
Views: 1690
Reputation: 5774
Your issue is the main div and mobile nav are two different AlpineJs components. The mobile nav has it's own x-data
instance and therefore it's own scope. When you're setting isDialogOpen
on the mobile nav component, nothing will happen to the modal because it's not inside that component. It's inside the parent component.
The solution here is to add your mobile isOpen
to the main component instance and remove the x-data
for the mobile nav:
<div x-data="{
isMobileNavOpen: false,
isDialogOpen: false,
}">
<nav id="main">
...
<span @click="isDialogOpen = true">Assessment</span>
</nav>
<nav id="mobile">
<button @click="isMobileNavOpen = !isMobileNavOpen"></button>
<div x-show="isMobileNavOpen">
...
<span @click="isDialogOpen = true">Assessment</span>
</div>
</nav>
<div
id="modal"
x-show="isDialogOpen"></div>
</div>
You may find using the AlpineJs Dev Tools helpful. Something that helps me a lot when this sort of thing is happening.
Also if at some point you need to be able to communicate between components check out Kevin Batdorf's Alpine Magic Helpers package 👌🏼
Upvotes: 1