angular-ui / ui-scroll

Unlimited bidirectional scrolling over a limited element buffer for AngularJS applications
http://angular-ui.github.io/ui-scroll/demo/
MIT License
326 stars 107 forks source link

How not to fetch invalid page if the total number of valid pages are already known ? #287

Closed aushwin closed 5 months ago

aushwin commented 5 months ago

Suppose each time we fetch 25 elements and the valid page is page 5. On Page 5 if the response comes with items less than 25 then the library knows that the next page is not availble and ends scroll hence will not request any API calls according to my datasource logic. But if the reponse returned from the API is exactly count then the library continues to scroll and request is send to the invalid page. I tried several ways to limit or control this but none of them seems to work... either the upward call breaks or duplicate elements are getting added. Am I missing something. Is it possible to end scroll with any other way if the valid pages are already known. I would really have some help here @dhilt

dhilt commented 5 months ago

@aushwin The scroller API implements an index-count approach. If you are talking about page-offset (suppose your backend supports only the page-offset API), then you need to provide a correct transformation at the datasource level. It may look like the following.

// mock data initialization
const pagesCount = 5;
const pageSize = 25;
const data = [];

for (let i = 0; i < pagesCount; i++) {
  data[i] = [];
  for (let j = 0; j < pageSize; j++) {
    const index = i * pageSize + j;
    data[i].push({
      index,
      text: 'test ' + index
    });
  }
}

// mock data fetch API
const getDataPage = pageOffset => {
  if (pageOffset < 0 || pageOffset >= pagesCount) {
    return [];
  }
  return data[pageOffset];
}

// index-count datasource implementation
const datasource = {
  get: (index, count, success) => {
    // items to request
    const startIndex = Math.max(index, 0);
    const endIndex = index + count - 1;
    if (startIndex > endIndex) {
      success([]); // empty result
      return;
    }

    // pages to request
    const startPage = Math.floor(startIndex / pageSize);
    const endPage = Math.floor(endIndex / pageSize);

    // pages result
    let pagesResult = [];
    for (let i = startPage; i <= endPage; i++) {
      pagesResult = [...pagesResult, ...getDataPage(i)];
    }

    // sliced result
    const start = startIndex - startPage * pageSize;
    const end = start + endIndex - startIndex + 1;
    const data = pagesResult.slice(start, end);

    success(data);
  }
};

The example is taken from https://dhilt.github.io/ngx-ui-scroll/#/datasource#pages. It is for the next Angular, but the idea of the datasource is the same. Also, in accordance with this particular example, you would need to provide the start-index setting (should be 0 in that case).

aushwin commented 5 months ago

@dhilt So this pageOffset will be my payload to the backend right? Forgot to mention, in my case, we can get the valid page only after the first response. In the first hit with page1 we get the total elements count (from where we can get the total number of valid page.) and an array of pageSize items.

aushwin commented 5 months ago

@dhilt Got it working. Thanks for sharing the doc 🙌

dhilt commented 5 months ago

Great! Thanks for using the library still.