1

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.

2
  • jsonplaceholder.typicode.com/photos returns 5000 photos. limit and offset is meaningless Commented May 19, 2022 at 3:17
  • @Doo9104 That is just a url I put since I can't share my real url. I just want to know how to implement offset and limit in a fetch request like this. Commented May 19, 2022 at 11:48

3 Answers 3

1
  • 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]
    
Sign up to request clarification or add additional context in comments.

1 Comment

fruits.slice(2, 1) got wrong result. Need do this: fruits.slice(offset, limit + offset)
0

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.

Comments

0

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">&larr;</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">&rarr;</button>
    </div>
  </div>
  <script src="./index.js"></script>
</body>

</html>

<!-- https://stackoverflow.com/questions/25434813/simple-pagination-in-javascript -->

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.