Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

After adding second element first element does not switch

I created function which create elements

function createElements(value) {
  //Create div .toggler
  const toggler = document.createElement('div');
  toggler.classList.add('toggler');

  //Create div .content
  const content = document.createElement('div');
  content.classList.add('content');

  //Append div .toggler in div .container
  container.append(toggler);

  //Append div .content in div .container
  container.append(content);

  toggler.innerText = 'Click me';
  content.innerText = value;
}

And function which should show and hide content if I’ll click toggler ‘Click me’

function toggleContent() {
  //Get created elements
  const togglers = document.querySelectorAll('.toggler'),
    contents = document.querySelectorAll('.content');

  //Toggle both div .active
  togglers.forEach((toggler, index) => {
    const content = contents[index];

    //Get div .content height
    const contentHeight = content.clientHeight + 'px';

    //Set div .content height
    content.style.height = '0px';

    //Toggle event
    toggler.addEventListener('click', () => {
      if (!toggler.classList.contains('active')) {
        toggler.classList.add('active');
      } else {
        toggler.classList.remove('active');
      }

      if (!content.classList.contains('active')) {
        content.classList.add('active');
        content.style.height = contentHeight;
      } else {
        content.classList.remove('active');
        content.style.height = '0px';
      }
    });
  });
}

Put these both functions in event of button

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

//Create html elements and set value inner them event
btn.addEventListener('click', () => {
  createElements(input.value);
  toggleContent();

  //Clear input value
  input.value = '';
  //   console.log(input.value);
});

All works fine, but if I add second element, first element toggler does not work

//Get html elements
const container = document.querySelector('.container'),
  input = document.querySelector('.input'),
  btn = document.querySelector('.btn');

function createElements(value) {
  //Create div .toggler
  const toggler = document.createElement('div');
  toggler.classList.add('toggler');

  //Create div .content
  const content = document.createElement('div');
  content.classList.add('content');

  //Append div .toggler in div .container
  container.append(toggler);

  //Append div .content in div .container
  container.append(content);

  toggler.innerText = 'Click me';
  content.innerText = value;
}

function toggleContent() {
  //Get created elements
  const togglers = document.querySelectorAll('.toggler'),
    contents = document.querySelectorAll('.content');

  //Toggle both div .active
  togglers.forEach((toggler, index) => {
    const content = contents[index];

    //Get div .content height
    const contentHeight = content.clientHeight + 'px';

    //Set div .content height
    content.style.height = '0px';

    //Toggle event
    toggler.addEventListener('click', () => {
      if (!toggler.classList.contains('active')) {
        toggler.classList.add('active');
      } else {
        toggler.classList.remove('active');
      }

      if (!content.classList.contains('active')) {
        content.classList.add('active');
        content.style.height = contentHeight;
      } else {
        content.classList.remove('active');
        content.style.height = '0px';
      }
    });
  });
}

//Create html elements and set value inner them event
btn.addEventListener('click', () => {
  createElements(input.value);
  toggleContent();

  //Clear input value
  input.value = '';
  //   console.log(input.value);
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.content {
  overflow: hidden;
}
    <input type="text" class="input" />
    <button class="btn">add</button>
    
    <div class="container">
      <!-- <div class="toggler"></div>
      <div class="content"></div> -->
    </div>

>Solution :

The first toggler (and subsequent ones as you add more elements) stop working because of 2 reasons:

  1. every time a new element is added you add another click listener to the existing elements (so when 2nd element is added, 1st element gets another click listener, this causes some weirdness later on)
  2. every time a new element is added for every existing item you remember their clientHeight so if they are actually in a collapsed state, you will store 0px to contentHeight so the new click handler will then be always using 0px also for expanded state height. It would be better to toggle display: none and display: block (or inline or inline-block whichever you need)

I moved the click handler registration to the first function, in this way every created element gets only one click handler.

I removed the clientHeight/contentHeight logic and just added a CSS rule so that .content items are visible when .active and not visible otherwise.
So the change was this part in CSS

.content {
  display: none;
}

.content.active {
   display: block;
}

I kept the logic that when you add a new item it will collapse all existing items. I think that is what you had in you logic too, but let me know if you don’t want that.

The change was in JS code

//Toggle both div .active
togglers.forEach((toggler, index) => {
    const content = contents[index];

    // I added this to keep the same logic you had before
    // if you would like to not collapse them, just remove the 2 lines
    toggler.classList.remove('active');
    content.classList.remove('active');
});
//Get html elements
const container = document.querySelector('.container'),
  input = document.querySelector('.input'),
  btn = document.querySelector('.btn');

function createElements(value) {
  //Create div .toggler
  const toggler = document.createElement('div');
  toggler.classList.add('toggler');

  //Create div .content
  const content = document.createElement('div');
  content.classList.add('content');

  //Append div .toggler in div .container
  container.append(toggler);

  //Append div .content in div .container
  container.append(content);

  toggler.innerText = 'Click me';
  content.innerText = value;

  toggler.addEventListener('click', () => {
      if (!toggler.classList.contains('active')) {
        toggler.classList.add('active');
      } else {
        toggler.classList.remove('active');
      }

      if (!content.classList.contains('active')) {
        content.classList.add('active');
      } else {
        content.classList.remove('active');
      }
    });
}

function toggleContent() {
  //Get created elements
  const togglers = document.querySelectorAll('.toggler'),
    contents = document.querySelectorAll('.content');

  //Toggle both div .active
  togglers.forEach((toggler, index) => {
    const content = contents[index];

    toggler.classList.remove('active');
    content.classList.remove('active');
  });
}

//Create html elements and set value inner them event
btn.addEventListener('click', () => {
  createElements(input.value);
  toggleContent();

  //Clear input value
  input.value = '';
  //   console.log(input.value);
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.content {
  display: none;
}

.content.active {
   display: block;
}
    <input type="text" class="input" />
    <button class="btn">add</button>
    
    <div class="container">
      <!-- <div class="toggler"></div>
      <div class="content"></div> -->
    </div>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading