skip to Main Content

I created simple collapse and expand mechanism by removing or adding the ‘active’ class. The removing mechanism works perfectly fine but I have a problem with adding active class on click:

const panelActive = document.querySelector('.panel');
const panelInactive = document.querySelectorAll('.panel:not(.active)');

// console.log(panelInactive);

const collaps = (event) => {
  console.log(event);
  panelActive.classList.remove('active');
};

const expand = (panel) => {
  console.log(panel);
  console.log(panel.classList);
  panel.classList.add('active');
};

panelInactive.forEach((panel) => {
  panel.addEventListener('click', collaps);
  panel.addEventListener('click', expand);
});

When the expand function is called, the .classList function returns an undefine value instead of a list of classes:
enter image description here
So I think thats the reason why it does not work at all.
Do you know how to fix it?

2

Answers


  1. This:

    panel.addEventListener('click', expand);
    

    Doesn’t pass any explicit arguments to expand(). The default implicit argument for an event handler is an event object. (In this case a PointerEvent.) Which you are observing when you do this:

    console.log(panel);
    

    And further observing that the event object has no classList property when you log this:

    console.log(panel.classList);
    

    The expand() function is expecting a "panel" to be provided, but you haven’t provided one. You can do so manually:

    panel.addEventListener('click', () => expand(panel));
    

    As an aside, the code is likely to have other problems as well. For example, the collaps() function will only ever "collapse" the "panel" that was originally expanded. No other panels would be affected.

    You can correct this by getting the "active panel" in the function itself, rather than only once when the page loads:

    const collaps = (event) => {
      console.log(event);
      document.querySelector('.panel').classList.remove('active');
    };
    
    Login or Signup to reply.
  2. Keep it easy – remove the active class from all panels on click, and add it to the clicked one:

    const panels = document.querySelectorAll('.panel');
    
    panels.forEach(panel => panel.addEventListener('click', (event) => {
      panels.forEach(panel => panel.classList.remove('active'));
      event.currentTarget.classList.toggle('active');
    }));
    .panel {
      margin-bottom: 1rem;
      background-color: orange;
      padding: .5rem;
    }
    
    .panel.active {
      background-color: dodgerblue;
    }
    
    .panel p {
      display: none;
    }
    
    .panel.active p {
      display: block;
    }
    <div class="panel">
      <h2>One</h2>
      <p>Content</p>
    </div>
    <div class="panel">
      <h2>Two</h2>
      <p>Content</p>
    </div>
    <div class="panel">
      <h2>Three</h2>
      <p>Content</p>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search