leonardeveloper
leonardeveloper

Reputation: 1853

Creating two modals on a single page using Alpine.js

I'm creating two modals on a single page and I'm having problem on how can I make it work. I just copied the example here and I converted it into a function like so:

function isDialogOpen() {
    return {
        modal: false,
        open() { this.modal = true;document.body.classList.add("modal-open"); },
        close() { this.modal = false;document.body.classList.remove("modal-open"); },
        isOpen() { return this.modal === true },
    }
}

These two modals is wrapped inside <main> element.

<main class="assignedquestion"  x-data="isDialogOpen()" @keydown.escape="close">

I've tried to do it something like this:

<main class="assignedquestion"  x-data="...isDialogOpen(), ...reassignDialog()" @keydown.escape="close">

And create another function with different variables and functions.

function reassignDialog() {
    return {
        reassignmodal: false,
        openReassign() { this.reassignmodal = true;document.body.classList.add("modal-open"); },
        closeReassign() { this.reassignmodal= false;document.body.classList.remove("modal-open"); },
        isOpenReassign() { return this.reassignmodal=== true },
    }
}

Unfortunately it doesn't work. Only the first modal is showing up.
These modal will be triggered by 2 different buttons.

Below is the markup of my modals:

First Modal

<!-- overlay -->
<div
    class="overflow-auto"
    style="background-color: rgba(0, 0, 0, 0.75);display:none"
    x-show="isOpen()"
    :class="{ 'user-history-modal': isOpen() }"
>
  <!-- dialog -->
  <div
       class="bg-white shadow-2xl"
       x-show="isOpen()"
       @click.away="close"
  >
      <div class="modal-header">
         <h3>Reassign Ticket</h3>
          <button type="button" @click="close"><svg width="14" height="14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13 1L1 13M1 1l12 12" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></button>
      </div>
      <div class="modal-content">
        
      </div>
  </div><!-- /dialog -->
</div><!-- /overlay -->

Second Modal

<!-- overlay reassignDialog -->
<div
    class="overflow-auto"
    style="background-color: rgba(0, 0, 0, 0.75);display:none"
    x-show="isOpenReassign()"
    :class="{ 'reassign-history-modal': isOpenReassign() }"
>
  <!-- dialog -->
  <div
       class="bg-white shadow-2xl"
       x-show="isOpenReassign()"
       @click.away="closeReassign"
  >
      <div class="modal-header">
         <h3>Reassign Ticket</h3>
          <button type="button" @click="closeReassign"><svg width="14" height="14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13 1L1 13M1 1l12 12" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></button>
      </div>
      <div class="modal-content">
        
      </div>
  </div><!-- /dialog -->
</div><!-- /overlay -->

Upvotes: 1

Views: 5533

Answers (2)

kenshuri
kenshuri

Reputation: 532

Modals (among other components) are now part of official AlpineJS documentation. Use them for perfect out of the box modals!

Upvotes: 0

Hugo
Hugo

Reputation: 3888

The solution here is to make each modal a separate component and to dispatch custom events to them to open/close them. That way, they'll be separate and you'll be able to close them independently. If only one of the modals can be open at a time, you should add @toggle-reassign-modal.window="close()" to the dialog modal (1st modal) and @toggle-modal.window="close()" to the reassign modal (2nd modal) so that they always close when the other modal is opened.

<div
  x-data="isDialogOpen()"
  @toggle-modal.window="modal = !modal"
  x-init="$watch('modal', (val) => { if (val) document.body.classList.add('modal-open') } )"
>
  <!-- contents of modal as per the question -->
</div>


<div
  x-data="reassignDialog()"
  @toggle-reassign-modal.window="reassignmodal = !reassignmodal"
  x-init="$watch('reassignmodal', (val) => { if (val) document.body.classList.add('modal-open') } )"
>
  <!-- contents of reassign modal as per the question -->
</div>

To trigger the modals to open you can use the following:

<!-- can remove x-data if these are inside of an Alpine component -->
<button x-data @click="$dispatch('toggle-modal')">Toggle Modal</button>
<button x-data @click="$dispatch('toggle-reassign-modal')">Toggle Reassign Modal</button>

You can see it working as a Codepen.

Upvotes: 3

Related Questions