0

I need to create a modal window when i click on AddExercise Button.In the first view the modal window should display the list of exercise categories and when user selects a particular category ,it should display the list of exercises under that category(the exercises list should be displayed in the same modal window).I am getting a Map object as response from controller(Map<String,List>)

  1. Is there any better way to achieve the above without having to add multiple eventListener inside one another? 2.Is it ok to have eventListener inside another eventListener? Here is my html code

let modal = document.getElementById("whole-modal-window");
let openModal = document.getElementById("open-modal");
let categoryContainer = document.getElementById("categoryModalBody");
let exerciseContainer = document.getElementById("exerciseModalBody");
let modalHeaderText = document.getElementById("modalHeaderText");
let exerciseLog=document.getElementById("exerciseLog");
let closeModal = document.querySelector(".close-modal");

  openModal.addEventListener('click', function () {
      event.preventDefault();
      modal.style.display = 'block';
      categoryContainer.innerHTML="";
      exerciseContainer.innerHTML="";//or try giving exerciseContainer.style.display='none';
      categoryContainer.style.display='block';
      modalHeaderText.innerHTML='Select Exercise';

            //make AJAX call to workout Controller to get the list of exercisecategory,the controller returns a Map(key being category and the value being the exercise list)

      $.ajax({

          url: "getExerciseCategories",
          method: "GET",
          success: function (response) {


          Object.keys(response).forEach(function (category) {
              var categoryLink = document.createElement("a");
              categoryLink.href = "#";
              categoryLink.innerHTML = category;


              //add event listener to the link to display exercises under that category
              categoryLink.addEventListener('click', function (event) {
                  event.preventDefault();
                  console.log("Inside exercise list");
                  categoryContainer.style.display = 'none';
                  exerciseContainer.style.display = 'block';
                  modalHeaderText.innerText = category;

                  //display exercises for clicked category
                  response[category].forEach(function (exercise) {

                      var exerciseLink = document.createElement("a");
                      exerciseLink.href = "#";
                      exerciseLink.innerHTML = exercise;


                      exerciseLink.addEventListener('click',function(event,exercise){
                          event.preventDefault();
                          let exerciseName=document.createElement("h2");
                          exerciseName.innerText=exercise;
                          exerciseLog.appendChild(exerciseName);
                          modal.style.display = 'none';

                      });
                      exerciseContainer.appendChild(exerciseLink);
                      exerciseContainer.appendChild(document.createElement("br"));


                  });


              });
              categoryContainer.appendChild(categoryLink);
              categoryContainer.appendChild(document.createElement("br"));

          });

      },

      error: function (xhr, status, error) {

      }

  }
  );


});

closeModal.addEventListener('click', function () {

    modal.style.display = 'none';
});

window.addEventListener('click', function (e) {
    if (e.target == modal) {
        modal.style.display = 'none';
    }
});
<button id="open-modal" type="button">Add Exercise</button> 
            <div id="exerciseLog"></div>
<div id="whole-modal-window">
    <div id="addExerciseModal" class="modal">
        <div id="modalContent">
            <div id="modalHeader">
                <span class="close-modal">&times;</span>
                <h2 id="modalHeaderText"></h2>
            </div>
            <div id="categoryModalBody">
            </div>
            <div id="exerciseModalBody">
            </div>
        </div>
    </div>
</div>

I wanted to know if its bad practice writing multiple event listener inside one another.

mmh4all
  • 1,612
  • 4
  • 6
  • 21
  • Is there any better approach that can be followed instead of adding multiple eventListener? – RulesofGames Mar 20 '23 at 08:47
  • 2
    In your case it seems to be OK to add an event listener inside in another listener. But, `exercise` is not passed to event handler because the handler is called from the event queue. You could also declare/store the handler function as a variable, that way the code wastes less memory. You can check [What is DOM event delegation](https://stackoverflow.com/q/1687296/1169519) to reduce listeners. – Teemu Mar 20 '23 at 08:47
  • Maybe don't use jQuery's AJAX - you'd just be loading in extra code unnecessarily when [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) is more than suitable. – Andy Mar 20 '23 at 08:52
  • 2
    There's two ways to provide events for dynamically created HTML - event delegation or adding the event directly after creating the element. Your "inner" event listener is only adding to the newly created elements, so it's a good way to add events. People have problems when they do things like "when I click, add an *additional* click event" etc. – freedomn-m Mar 20 '23 at 09:39

0 Answers0