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
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>
You can try to add “!important” at the final of your your css properties.
For example:
ul {
list-style: none !important;
padding: 0 !important;
}
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);
}
CSS is automatically applied to all content in the DOM no matter when it’s created. As such your example works fine:
Thanks! That sorted it.