2

I am attempting to create dynamic modal popups from query feeds in WordPress. One feed displays elements that need to be clicked and one feed holds the content for the modal popups. My current code adds an iterated id to all elements with a certain class if the parent has a certain id. This is occuring for the two different parent containers.

My problem is I want it to work so when you click on id="team-0" it will open the corresponding id="modal-0";

Here is my javascript:

const modalContainer = document.getElementById('modalContainer');
const modal = modalContainer.querySelectorAll('.team');

  modal.forEach((element, index) => {
    element.id = `modal-${index}`;
  });

const teamContainer = document.getElementById('teamContainer');
const team = teamContainer.querySelectorAll('.team');

  team.forEach((element, index) => {
    element.id = `team-${index}`;
  });

The HTML looks similar to this:

<div id="teamContainer">
<ul>
<li id="team-0" class="team"></li>
<li id="team-1" class="team"></li>
<li id="team-2" class="team"></li>
</ul>
</div>

<div id="modalContainer">
<ul>
<li id="modal-0" class="team"></li>
<li id="modal-1" class="team"></li>
<li id="modal-2" class="team"></li>
</ul>
</div>

The current way I am trying to make this work (but I understand if this is just completely wrong):

window.onload = function(){ 
  for (let i = 0; i < 10; i++) {
    let teamId = `team-${i}`;
    let teamIndex = document.getElementById(teamId);

    let modalId = `modal-${i}`;
    let modalIndex = document.getElementById(modalId);

    teamIndex.onclick = function() {
      modalIndex.style.display = "block";
    }
  }
};

Thank you for any responses and let me know if you need more information.

4
  • If you want a modal, you'll likely need to use the <dialog> element. If not, what do you mean by "open"? It seems to be setting the modalIndex's style correctly. Commented Sep 11, 2024 at 20:52
  • Sorry, by "open" I mean if I can target the element with the corresponding id, it will add the style "display:block"; Right now, I am getting an "Uncaught TypeError: Cannot set properties of null (setting 'onclick')" on the "teamIndex.onclick = function()" Commented Sep 11, 2024 at 21:03
  • I just check and you seem to be correct, it does seem that it setting the style correctly. I will need to do some further testing. Thank you for the response! Commented Sep 11, 2024 at 21:07
  • Do you create the same count of modal and team elements as you have in your loop after the window.onload definition? Commented Sep 11, 2024 at 21:42

1 Answer 1

1

You can toggle display using a helper class. If you want the "modals" to all be invisible then initially add a class that sets their display to none or just change in your CSS.

I added buttons to the list items for the teams as buttons/inputs are for clicks events. Use the event.target of the button to travel up the DOM and get a parent element to query the modal elements list.

Query over the team classes and get the closest div element for the team buttons and then get its parentNode, use that to query the modal groups div ul listItems => #modalContainer li. Iterate over them and use the index in the forEach loop to add a helper class to show the proper modal.

I have added a basic snippet showing this logic and further comments in the snippet. Let me know if anything is unclear or if this is not what you were looking for.

NOTE: Keep in mind using this logic would mean your listItems for teams and modals must have the same amount of index and each index would need to match.

Using something like a data-attribute => <li id="modal-1" class="team" data-team-id='team-1'> in your 'modal' would be a more robust approach. Then you could query on a click eventListsner using something like e.target.querySelector('[data-modal-id="${e.target.id}"]')

const teams = document.querySelectorAll('.team button');
const modals = document.querySelectorAll('#modalContainer li');

// set your "modals" to display of none initially
modals.forEach(modal => {
  modal.classList.add('modals');
})

// loop over the teams
teams.forEach((team, i) => {
  // click event listener passing in event
  team.addEventListener('click', (e) => {
    // get the parent of the button groups div
    const parent = e.target.closest('div').parentNode;  
    // get the modals using the team buttons parent element
    const modalList = parent.querySelectorAll('#modalContainer li');
    // iterate over the modal elements and remove any `show` helper class
    modalList.forEach(list => {
      list.classList.remove('show');
    });
    // get the corresponding modal for the teams index from forEach methods index param
    const target = modals[i];
    // add the show class to view the modal that matches your teams index
    target.classList.add('show');
  });
})
.modals {
  display: none;
}

.show {
  display: block;
}
<div id="teamContainer">
  <ul>
    <li id="team-0" class="team">
      <button>Team 1</button>
    </li>
    <li id="team-1" class="team">
      <button>Team 2</button>
    </li>
    <li id="team-2" class="team">
      <button>Team 3</button>
    </li>
    <li id="team-20" class="team">
      <button>Team 20</button>
    </li>
    <li id="team-999" class="team">
      <button>Team 999</button>
    </li>
  </ul>
</div>

<div id="modalContainer">
  <ul>
    <li id="modal-0" class="team">Modal for team 1</li>
    <li id="modal-1" class="team">Modal for team 2</li>
    <li id="modal-2" class="team">Modal for team 3</li>
    <li id="modal-20" class="team">Modal for team 20</li>
    <li id="modal-999" class="team">Modal for team 999</li>
  </ul>
</div>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.