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 >Show modal 1</button>
<button >Show modal 2</button>
<div >
<button >×</button>
<p>Content1</p>
</div>
<div >
<button >×</button>
<p>Content2</p>
</div>
<div ></div>
CodePudding user response:
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 >Show modal 1</button>
<button >Show modal 2</button>
<div >
<button >×</button>
<p>Content1</p>
</div>
<div >
<button >×</button>
<p>Content2</p>
</div>
<div ></div>
CodePudding user response:
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 >
<button data-id="one">
Show modal 1
</button>
<button data-id="two">
Show modal 2
</button>
</div>
<div >
<div >
<button >×</button>
</div>
<div >
<p>1</p>
</div>
</div>
Additional information