Reputation: 49
I have a huge data being returned from a fetch api call. I want to limit the displayed data to 10 per page and have more data returned when the next page button is clicked. How can I implement that?
limit is set to 10 and offset is set to 0. The maximum data that can be returned per page is 150.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<button class = B1 id="photos">View photos</button>
<div id="showResults"></div>
<div>
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item">
<button class="page-link" id="nextButton">Next</button>
</li>
</ul>
</nav>
</div>
<script>
let limit = 10;
let offset = 0;
const showPhoto = (key, value) => {
const pre_x = document.createElement("pre");
const dt_x = document.createElement("dt");
const dd_x = document.createElement("dd")
dt_x.textContent = key;
pre_x.appendChild(dt_x);
{
dd_x.textContent = value;
}
pre_x.appendChild(dd_x);
return pre_x;
};
const structurePhotos = (obj) => {
const dl = document.createElement("dl");
for (let k in obj) {
let j = obj[k];
if (typeof obj[k] === "object") {
j = JSON.stringify(obj[k], null, 2);
}
dl.appendChild(showPhoto(k, j));
}
return dl;
};
function getPhotos(url) {
fetch(url)
.then((res) => (res.ok ? res.json() : Promise.reject(res)))
.then((data) => {
if (Array.isArray(data)) {
data.forEach((photo) => {
showResults.append(
structurePhotos(photo),
);
});
}
})
.catch(console.error);
}
const photos = document.getElementById("photos");
photos.addEventListener(
"onclick",
getPhotos(`https://jsonplaceholder.typicode.com/photos`)
);
</script>
</body>
</html>
limit is set to 10 and offset is set to 0. The maximum data that can be returned per page is 150.
Upvotes: 1
Views: 8721
Reputation: 516
My situation was the same as yours. I was also looking for a pagination system where I will be able to paginate my data along with index and offset. But couldn't get any satisfactory solution out there. Finally, I made it myself. Maybe it's gonna help others.
const listEl = document.querySelector(".list");
const pageIndexEl = document.querySelector(".page-index");
const prevBtn = document.querySelector(".prev");
const nextBtn = document.querySelector(".next");
const items = Array.from(listEl.children);
const itemPerPage = 5;
const navPerPage = 3;
const pagingItems = pagingItemsArr();
let currentActive = 0;
nextBtn.addEventListener("click", e => {
currentActive++;
if (currentActive > pagingItems.length) {
currentActive = pagingItems.length;
}
update();
});
prevBtn.addEventListener("click", e => {
currentActive--;
if (currentActive < 0) {
currentActive = 0;
}
update();
});
function btnControl() {
if (currentActive == 0) {
prevBtn.disabled = true;
} else if (currentActive == pagingItems[pagingItems.length - 1]) {
nextBtn.disabled = true;
} else {
nextBtn.disabled = false;
prevBtn.disabled = false;
}
}
function update() {
const temp = Array.from(pageIndexEl.children);
temp.forEach((item, idx) => {
if (idx == currentActive) {
removeActiveClass();
item.classList.add("active");
} else {
item.classList.remove("active");
};
});
btnControl();
let currentlyShowing = temp.filter(item => !item.classList.contains("hide"));
if (currentActive == currentlyShowing[currentlyShowing.length - 1].dataset.id) {
const arr = temp.slice(currentActive, navPerPage + currentActive);
updatePaging(arr);
}
if (currentActive == currentlyShowing[0].dataset.id - 2) {
const arr = temp.slice(Math.floor(currentActive - (navPerPage - 1)), (2 + currentActive) - 1);
updatePaging(arr);
}
showPaginatedItems(currentActive + 1);
}
function updatePaging(arr) {
const allItem = Array.from(pageIndexEl.children);
allItem.forEach(item => {
if (!item.classList.contains("hide")) {
item.classList.add("hide");
}
});
allItem.filter(item => arr.includes(item))
.forEach(item => item.classList.remove("hide"));
}
function removeActiveClass() {
const actives = document.querySelectorAll(".active");
actives.forEach(item => item.classList.remove("active"));
}
function displayPagingItems() {
pageIndexEl.innerHTML = "";
pagingItems.forEach((item, idx) => {
pageIndexEl.innerHTML += `<li
${idx == 0 ? "class='active'" : ""}
${idx >= navPerPage ? "class='hide'" : ""}
data-id="${idx + 1}"
>${item}</li>
`;
});
}
function pagingItemsArr() {
const totalPage = Math.ceil(items.length / itemPerPage);
const arr = [];
for (let i = 0; i < totalPage; i++) {
arr.push(i);
}
return arr;
}
function showPaginatedItems(pageIndex = 1) {
const itemsArr = items.slice((pageIndex - 1) * itemPerPage, pageIndex * itemPerPage);
listEl.innerHTML = "";
itemsArr.forEach(item => {
listEl.innerHTML += `<li>${item.innerText}</li>`;
});
}
function init() {
displayPagingItems();
btnControl();
showPaginatedItems();
}
init();
.app-container {
max-width: 500px;
min-height: 100vh;
margin: 0 auto;
}
.list {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
list-style-type: none;
}
.list li {
background-color: #999;
width: 100%;
margin: 10px 0;
text-align: center;
}
.btn-container {
display: flex;
align-items: center;
justify-content: space-evenly;
margin: 20px 0;
}
.btn {
padding: 5px 10px;
cursor: pointer;
}
.btn:disabled {
cursor: not-allowed;
}
.page-index li {
background-color: #fff;
border: 1px solid #999;
border-radius: 2px;
display: inline-flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
margin: 0 5px;
cursor: pointer;
transition: 0.1s ease-in-out;
}
.page-index li.hide {
display: none;
}
.page-index li.active {
background-color: #ddd;
}
.page-index li:focus,
.page-index li:hover {
background-color: #ddd;
}
.page-index li:focus,
.page-index li:active,
.page-index li.active:focus,
.page-index li.active:active {
transform: scale(0.95);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pagination</title>
</head>
<body>
<div class="app-container">
<ul class="list">
<li class="active">List1</li>
<li>List2</li>
<li>List3</li>
<li>List4</li>
<li>List5</li>
<li>List6</li>
<li>List7</li>
<li>List8</li>
<li>List9</li>
<li>List10</li>
<li>List11</li>
<li>List12</li>
<li>List13</li>
<li>List14</li>
<li>List15</li>
<li>List16</li>
<li>List17</li>
<li>List18</li>
<li>List19</li>
<li>List20</li>
<li>List21</li>
<li>List22</li>
<li>List23</li>
<li>List24</li>
<li>List25</li>
<li>List26</li>
<li>List2</li>
<li>List28</li>
<li>List29</li>
<li>List30</li>
<li>List31</li>
<li>List32</li>
<li>List33</li>
<li>List34</li>
<li>List35</li>
<li>List36</li>
</ul>
<div class="btn-container">
<button class="btn prev">←</button>
<ul class="page-index">
<!-- <li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li> -->
</ul>
<button class="btn next">→</button>
</div>
</div>
<script src="./index.js"></script>
</body>
</html>
<!-- https://stackoverflow.com/questions/25434813/simple-pagination-in-javascript -->
Upvotes: 0
Reputation: 36
Use Javascript built-in array function slice()
For Ex:
let fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango"];
fruits.slice(0, 3); // 0 => offset, 3 => limit
output
output => [Banana,Orange,Lemon]
Upvotes: 1
Reputation: 14259
If you can not change the backend/API to use pagination - you can use the following function to split the Array with results from the API into smaller chunks:
function arrChunk(arr, size)
{
return arr.reduce((acc, e, i) =>
{
if (i % size)
{
acc[acc.length - 1].push(e);
}
else
{
acc.push([e]);
}
return acc;
}, []);
}
But the best option is to change the backend and avoid transferring excessive data over the network.
Upvotes: 0