daniel
daniel

Reputation: 31

How to add different content for different modals vanilla JavaScript

So I want to have some buttons opening modals with different content. But when I click them, the same content appears. How do I link them properly? (I have never asked in here so forgive me if I did any mistakes)

const modal = document.querySelector('.modal');
const overlay = document.querySelector('.overlay');
const btnCloseModal = document.querySelector('.close-modal');
const btnsOpenModal = document.querySelectorAll('.show-modal');
const openModal = function () {
  modal.classList.remove('hidden');
  overlay.classList.remove('hidden');
};

const closeModal = function () {
  modal.classList.add('hidden');
  overlay.classList.add('hidden');
};

for (let i = 0; i < btnsOpenModal.length; i++)
btnsOpenModal[i].addEventListener('click', openModal);
btnCloseModal.addEventListener('click', closeModal);
overlay.addEventListener('click', closeModal);
.hidden {
  display: none;
}
<button class="show-modal">Show modal 1</button>
    <button class="show-modal">Show modal 2</button>
    <div class="modal hidden">
      <button class="close-modal">&times;</button>
      <p>Content1</p>
   </div>
   <div class="modal hidden">
    <button class="close-modal">&times;</button>
    <p>Content2</p>
  </div>
    <div class="overlay hidden"></div>

Upvotes: 0

Views: 255

Answers (2)

Andy
Andy

Reputation: 63550

At the moment querySelector('.modal') is only picking up one modal, and you have no way of identifying which button relates to what modal.

Generally you have one modal, and then update the modal content with JavaScript. So that's what this example does. It has one modal, and the buttons are identified by a data attribute. Further: the content you want to update is stored in an object.

When a button is clicked (see event delegation) we get the data attribute value, grab the content from the object, update the modal content, and then show the modal.

// Cache the elements - one modal, one close-modal
// button, a button container, and the paragraph in the modal
const modal = document.querySelector('.modal');
const para = modal.querySelector('.modal-content p')
const close = document.querySelector('.close-modal');
const buttons = document.querySelector('.buttons');

// Add one event listener to the button container to 
// catch events from its child elements (the buttons),
// and one to the close-modal button
buttons.addEventListener('click', handleClick);
close.addEventListener('click', handleClose);

// Content
const modalContent = {
  one: "This is the first modal content",
  two: "This is the second modal content"
};

// When the button container catches an event...
function handleClick(e) {

  // We check that it's from a button...
  if (e.target.matches('.show-modal')) {

    // ...destructure the id from the button's dataset...
    const { id } = e.target.dataset;

    // ...use it to get the content from the object...
    const content = modalContent[id];

    // ...and add the content to the paragraph element
    para.textContent = content;

    // Finally we show the modal
    modal.classList.remove('hidden');
  }
}

function handleClose() {
  modal.classList.add('hidden');
}
.hidden {
  display: none;
}

.modal {
  position: fixed;
  inset: 0;
  background-color: lightblue;
  opacity: 0.8;
  margin: 1.5em;
  border: 2px solid #343434;
  overflow: hidden;
  transition: all 0.3s ease-in-out; z-index: 999; 
}

.modal-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.close-modal {
  position: relative;
  left: 0;
  top: 0;
}
<div class="buttons">
  <button class="show-modal" data-id="one">
    Show modal 1
  </button>
  <button class="show-modal" data-id="two">
    Show modal 2
  </button>
</div>

<div class="modal hidden">
  <div class="modal-header">
    <button class="close-modal">&times;</button>
  </div>
  <div class="modal-content">
    <p>1</p>
  </div>
</div>

Additional information

Upvotes: 1

Seangle
Seangle

Reputation: 668

You need to tell the program what modal to open. For this, you need to make each model unique, for this, you can use IDs, or Indexes, depending on the specific case. Also, if your HTML contains multiple elements of the same class, you should use querySelectorAll() most of the times, since it returns an array of all the elements, unlike querySelector(), which only selects the first found element.

const modals = document.querySelectorAll('.modal');
const overlay = document.querySelector('.overlay');
const btnsCloseModal = document.querySelectorAll('.close-modal');
const btnsOpenModal = document.querySelectorAll('.show-modal');

function openModal(i) {
  closeModal()
  modals[i].classList.remove('hidden');
  overlay.classList.remove('hidden');
};

function closeModal() {
  for (let i = 0; i < modals.length; i++) {
    modals[i].classList.add('hidden');
  }
  overlay.classList.add('hidden');
};
for (let i = 0; i < btnsOpenModal.length; i++) {
  btnsOpenModal[i].addEventListener('click', () => {
    openModal(i)
  }, false);
}
for (let i = 0; i < btnsCloseModal.length; i++) {
  btnsCloseModal[i].addEventListener('click', closeModal, false);
}
overlay.addEventListener('click', closeModal, false);
.hidden {
  display: none;
}

.overlay {
  position: fixed;
  inset: 0;
  background: #0007;
  z-index: 5;
}

.modal {
  position: fixed;
  background: #eee;
  z-index: 10;
  top: 50vh;
  left: 50vw;
  transform: translate(-50%, -50%);
  padding: 0.5rem;
  border-radius: 0.5rem;
}
<button class="show-modal">Show modal 1</button>
<button class="show-modal">Show modal 2</button>
<div class="modal hidden">
    <button class="close-modal">&times;</button>
    <p>Content1</p>
</div>
<div class="modal hidden">
    <button class="close-modal">&times;</button>
    <p>Content2</p>
</div>
<div class="overlay hidden"></div>

Upvotes: 0

Related Questions