Solution 1 :

You need to delegate the event from ul since li & a are dynamically created
Replace $('.toggle').click(function(e) { with $('ul').on('click', 'li a.toggle', function(e) {

jsonplaceholder public api is used to create stack snippte

$(document).ready(function() {
  $.getJSON('https://jsonplaceholder.typicode.com/posts', function(data) {

    $.each(data, function(index, value) {
      $('.accordion').append(`<li><a class='toggle'>Q: ${value.title}</a>
      <p class='inner'>${value.body}</p></li>`);
    });
  });

  // Accordion animation

  $('ul').on('click', 'li a.toggle', function(e) {
    e.preventDefault();

    let $this = $(this);

    if ($this.next().hasClass('show')) {
      $this.next().removeClass('show');
      $this.next().slideUp(350);
    } else {
      $this.parent().parent().find('li .inner').removeClass('show');
      $this.parent().parent().find('li .inner').slideUp(350);
      $this.next().toggleClass('show');
      $this.next().slideToggle(350);
    }
  });
})
* {
  box-sizing: border-box;
  font-family: 'Roboto', sans-serif;
  font-weight: 300;
}

a {
  text-decoration: none;
  color: inherit;
}

body {
  width: 40%;
  min-width: 300px;
  max-width: 500px;
  margin: 1.5em auto;
  color: #333;
}

h1 {
  font-weight: 400;
  font-size: 2.5em;
  text-align: center;
  margin-top: 5rem;
}

ul {
  list-style: none;
  padding: 0;
}

ul .inner {
  padding-left: 1em;
  overflow: hidden;
  display: none;
}

ul li {
  margin: 0.5em 0;
}

ul li a.toggle {
  width: 100%;
  display: block;
  background: rgba(0, 0, 0, 0.78);
  color: #fefefe;
  padding: 0.75em;
  border-radius: 0.15em;
  transition: background 0.3s ease;
}

ul li a.toggle:hover {
  background: rgba(0, 0, 0, 0.9);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="accordion">

</ul>

After clicking run button wait for few seconds to completely load the demo

Solution 2 :

When you add new HTML to your page after the page has loaded, it comes without any event handlers. The easiest way to fix this is to remove and add again the event handlers for your accordion after you have updated your HTML. This could be done something like this:

$(document).ready(function() {
  $.getJSON('file.json', function(data) {
    $.each(data.file, function(index, value) {
      $('.accordion').append(`<li><a class='toggle'>Q: ${value.question}</a>
      <p class='inner'>${value.answer}</p></li>`);
    });
    
    //remove and add toggle handler again
    $('.toggle').unbind('click');
    addToggleHandler()
  });
  
  addToggleHandler();
});

 
function addToggleHandler(){
  $('.toggle').click(function(e) {
      e.preventDefault();
    
      let $this = $(this);
    
      if ($this.next().hasClass('show')) {
          $this.next().removeClass('show');
          $this.next().slideUp(350);
      } else {
          $this.parent().parent().find('li .inner').removeClass('show');
          $this.parent().parent().find('li .inner').slideUp(350);
          $this.next().toggleClass('show');
          $this.next().slideToggle(350);
      }
  });
}


  
<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="//code.jquery.com/jquery-2.1.3.min.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <ul class="accordion">

    </ul>
  </body>

</html>

Solution 3 :

You can try to add “!important” at the final of your your css properties.
For example:

ul {
 list-style: none !important;
  padding: 0 !important;
}

Problem :

I’ve been scouring the internet for an answer to this but can’t figure it out.

I’ve been trying to create an accordion, in which I append data from a JSON file. When I append the list items, the classes are not properly applied, so the accordion animation no longer works. I can see this when I inspect the html in the console. Any ideas?

My index file:

<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="//code.jquery.com/jquery-2.1.3.min.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <ul class="accordion">

    </ul>
  </body>

</html>

My JS file:

$(document).ready(function() {
  $.getJSON('file.json', function(data) {
    $.each(data.file, function(index, value) {
      $('.accordion').append(`<li><a class='toggle'>Q: ${value.question}</a>
      <p class='inner'>${value.answer}</p></li>`);
    });
  });

  // Accordion animation

  $('.toggle').click(function(e) {
      e.preventDefault();
    
      let $this = $(this);
    
      if ($this.next().hasClass('show')) {
          $this.next().removeClass('show');
          $this.next().slideUp(350);
      } else {
          $this.parent().parent().find('li .inner').removeClass('show');
          $this.parent().parent().find('li .inner').slideUp(350);
          $this.next().toggleClass('show');
          $this.next().slideToggle(350);
      }
  });
})

My CSS:

* {
  box-sizing: border-box;
  font-family: 'Roboto', sans-serif;
  font-weight: 300;
}

a {
  text-decoration: none;
  color: inherit;
}

body {
  width: 40%;
  min-width: 300px;
  max-width: 500px;
  margin: 1.5em auto;
  color: #333;
}

h1 {
  font-weight: 400;
  font-size: 2.5em;
  text-align: center;
  margin-top: 5rem;
}

ul {
  list-style: none;
  padding: 0;
}

ul .inner {
  padding-left: 1em;
  overflow: hidden;
  display: none;
}

ul li {
  margin: 0.5em 0;
}

ul li a.toggle {
  width: 100%;
  display: block;
  background: rgba(0, 0, 0, 0.78);
  color: #fefefe;
  padding: 0.75em;
  border-radius: 0.15em;
  transition: background 0.3s ease;
}

ul li a.toggle:hover {
  background: rgba(0, 0, 0, 0.9);
}

Comments

Comment posted by jsfiddle.net/RoryMcCrossan/csdLv8he

CSS is automatically applied to all content in the DOM no matter when it’s created. As such your example works fine:

Comment posted by tocky

Thanks! That sorted it.

By

Leave a Reply

Your email address will not be published. Required fields are marked *