I’ve set up a template literal that feeds a list of events to the page. There’s also a "Load More" button that pushes an additional event to the page each time the button is clicked.
I’ve already got a ternary statement indicating that if the events list is empty, a message "There’s nothing here." will display.
…but the "Load More" button still displays. If there are no events, then there should be no "Load More" button.
How can I hide the "Load More" button when the events array is empty.
const events = [
{
eventsLink: "",
eventsTitle: "",
eventsSubTitle: "",
eventsText: "",
eventsRegText: ""
}
];
// const events = [
// {
// eventsLink: "https://dev.to",
// eventsTitle: "Hello Dev",
// eventsSubTitle: "Dev is here...",
// eventsText: "Nextiva is proud to participate in Telarus",
// eventsRegText: "Register Now"
// },
// {
// eventsLink: "",
// eventsTitle: "Hello Mozilla",
// eventsSubTitle: "Mozilla is here...",
// eventsText: "Held in Napa, the heart of the California",
// eventsRegText: "Register Coming!"
// },
// {
// eventsLink: "https://www.google.com",
// eventsTitle: "Hello Google",
// eventsSubTitle: "Google is here...",
// eventsText: "Held in Silicon Valley, the heart of the technology",
// eventsRegText: "Register Today!"
// }
// ];
function eventsPageTemplate(event) {
return `
${
(event.eventsTitle,
event.eventsSubTitle,
event.eventsText,
event.eventsRegText
? `
<div class="col-sm-12 col-md-6 col-lg-4 event-item">
<div class="card m-1">
<div class="card-body">
<h5 class="card-title">${event.eventsTitle}</h5>
<h6 class="card-subtitle mb-2 text-muted">${
event.eventsSubTitle
}</h6>
<p class="card-text">${event.eventsText}</p>
${
event.eventsLink
? `<a href="${event.eventsLink}" class="card-link stretched-link">${event.eventsRegText}</a>`
: ``
}
</div>
</div>
</div>
`
: `
<div class="col-sm-12">
<div class="card">
<div class="card-body">
There's nothing here.
</div>
</div>
</div>
`)
}
`;
}
document.getElementById("eventsList").innerHTML = `${events
.map(eventsPageTemplate)
.join(" ")}`;
//load more functionality
let list = document.querySelector("#listEvents");
let items = Array.from(list.querySelectorAll(".event-item"));
let loadMore = document.getElementById("loadMore");
maxItems = 1;
loadItems = 1;
hiddenClass = "hiddenStyle";
hiddenItems = Array.from(document.querySelectorAll(".hiddenStyle"));
items.forEach(function (item, index) {
console.log(item.innerText, index);
if (index > maxItems - 1) {
item.classList.add(hiddenClass);
}
});
loadMore.addEventListener("click", function () {
[].forEach.call(
document.querySelectorAll("." + hiddenClass),
function (item, index) {
if (index < loadItems) {
item.classList.remove(hiddenClass);
}
if (document.querySelectorAll("." + hiddenClass).length === 0) {
loadMore.style.display = "none";
}
}
);
});
.hiddenStyle {
position: absolute;
overflow: hidden;
clip: rect(0 0 0 0);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
border: 0;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css">
<div class="container p-3" id="listEvents">
<div class="row" id="eventsList"></div>
<div class="row mt-3">
<div class="load-more-button mx-auto">
<a class="btn btn-md btn-primary text-white" id="loadMore">Load More</a>
</div>
</div>
</div>
2
Answers
I’m not sure what you intended to do with
[].forEach.call(...)
.The load more button’s onclick handler does get fired. You need to reorganise the click handler logic:
See working snippet below.
I am going to suggest to not use templates, put the elements in the markup (hidden) and clone them instead of a problematic string manipulation to inject HTML.
Not sure what your intent is with the global undeclared and your
loadMore
is about so I left it alone just to illustrate what I would propose.