Search code examples
javascriptgoogle-drive-api

Why previous page only works if there's 2 pages (Google Drive API)


I've encountered a problem, probably it's not something huge. So basically I'm using Google Drive API to retrieve files from drive and I want to make pagination, I managed to do next page just fine, but the problem rised when I tried implementing Previous Page button. Imanaged to make it work, but now if there's 2 pages it works just fine, but if there's more than 2, for example, if there are 3 pages, if I go to 3rd page, click Previous Page button, it takes me to 2nd page, but then there's no "previousPageToken" so button is not appearing at all. Should I store tokens in an array or something like that? Here is the code:


let currentPageToken = null;
let previousPageToken = null;

async function listFiles(folderId, pageToken = null) {
  $('#table_content').empty();
  $('#table_content').remove();
  isListFilesInProgress = true; // Set the flag to indicate listFiles() is in progress

  // Disable the button during listFiles() execution
  $('#show_files_button').prop('disabled', true);

  const request = {
    q: `'${folderId}' in parents`,
    pageSize: 10,
    fields: 'nextPageToken, files(id, name, mimeType, thumbnailLink, webContentLink, modifiedTime)',
    pageToken: pageToken, // Pass the pageToken to retrieve the next page
  };

  gapi.client.drive.files
    .list(request)
    .then(function (response) {
      console.log(response);
      var files = response.result.files;
      if (files && files.length > 0) {
        var table = document.createElement('table');
        table.classList.add('table', 'table-striped');
        table.id = 'table_content';

        var thead = document.createElement('thead');
        var headerRow = document.createElement('tr');
        var header1 = document.createElement('th');
        header1.textContent = 'Thumbnail';
        var header2 = createSortableHeader('Name', 'name');
        var header3 = createSortableHeader('Type', 'mimeType');
        var header4 = createSortableHeader('Last Updated', 'modifiedTime');
        var header5 = document.createElement('th');
        header5.textContent = 'Download';

        headerRow.appendChild(header1);
        headerRow.appendChild(header2);
        headerRow.appendChild(header3);
        headerRow.appendChild(header4);
        headerRow.appendChild(header5);
        thead.appendChild(headerRow);
        table.appendChild(thead);

        var tbody = document.createElement('tbody');
        for (var i = 0; i < files.length; i++) {
          (function (file) {
            var fileName = file.name;
            var mimeType = file.mimeType;
            var thumbnailLink = file.thumbnailLink;
            var downloadLink = file.webContentLink;
            var lastUpdated = new Date(file.modifiedTime).toLocaleString();
            var fileId = file.id;

            var row = document.createElement('tr');

            var thumbnailCell = createThumbnailCell(thumbnailLink, mimeType, fileId);
            row.appendChild(thumbnailCell);

            var nameCell = document.createElement('td');
            nameCell.textContent = fileName;
            row.appendChild(nameCell);

            var typeCell = document.createElement('td');
            typeCell.textContent = mimeType;
            row.appendChild(typeCell);

            var lastUpdatedCell = document.createElement('td');
            lastUpdatedCell.textContent = lastUpdated;
            row.appendChild(lastUpdatedCell);

            if (mimeType != 'application/vnd.google-apps.folder') {
              var downloadCell = document.createElement('td');
              var downloadLinkElem = document.createElement('a');
              downloadLinkElem.href = downloadLink;
              downloadLinkElem.textContent = 'Download';
              downloadLinkElem.classList.add('btn', 'btn-primary');
              downloadLinkElem.target = '_blank';
              downloadCell.appendChild(downloadLinkElem);
              row.appendChild(downloadCell);
            }

            // Add click event listener to navigate into folders
            if (mimeType === 'application/vnd.google-apps.folder') {
              row.classList.add('folder-row');
              row.addEventListener('click', function () {
                var folderId = file.id;
                listFiles(folderId);
              });
            }

            tbody.appendChild(row);
          })(files[i]);
        }

        table.appendChild(tbody);
        document.getElementById('content').appendChild(table);

        // Remove existing Next Page and Previous Page buttons
        $('.next-page-button').remove();
        $('.previous-page-button').remove();

        // Add Next Page button if there is a nextPageToken
        const nextPageToken = response.result.nextPageToken;
        if (nextPageToken) {
          const nextPageButton = document.createElement('button');
          nextPageButton.textContent = 'Next Page';
          nextPageButton.classList.add('btn', 'btn-primary', 'next-page-button');
          nextPageButton.addEventListener('click', function () {
            listFiles(folderId, nextPageToken); // Call listFiles() with the nextPageToken
          });

          document.getElementById('content').appendChild(nextPageButton);
        }

        // Add Previous Page button if there is a pageToken
        if (pageToken) {
          const previousPageButton = document.createElement('button');
          previousPageButton.textContent = 'Previous Page';
          previousPageButton.classList.add('btn', 'btn-primary', 'previous-page-button');
          previousPageButton.addEventListener('click', function () {
            listFiles(folderId); // Call listFiles() without the pageToken to go back to the previous page
          });

          document.getElementById('content').appendChild(previousPageButton);
        }
      }
    })
    .finally(function () {
      isListFilesInProgress = false;
      $('#show_files_button').prop('disabled', false);
    });
}

To sum up, I can only go back one page and it stops there, therefore I can go to next page just fine, because there is always a token for next page.

Thank you in advance!

Edit:

So as suggested I tried keeping page tokens in an array, I push it into an array and on the next function call (when next page is clicked), token is taken from array and I checked with console.log() that token is assigned to previousPageToken, but for some reason on the next page when I press Previous Page button it now just refreshes same page, this is the code of button creation:

const previousPageToken = pageTokens[pageTokens.length - 1];

          console.log('next');
          console.log(nextPageToken);
          console.log('previous');
          console.log(previousPageToken);
          
          if (previousPageToken) {
            const previousPageButton = document.createElement('button');
            previousPageButton.textContent = 'Previous Page';
            previousPageButton.classList.add('btn', 'btn-primary', 'previous-page-button');
            previousPageButton.addEventListener('click', function () {
              listFiles(folderId, previousPageToken); // Call listFiles() with the previousPageToken
            });

            document.getElementById('content').appendChild(previousPageButton);
          }


Solution

  • So I finally managed to solve this problem, so I'll post an answer, maybe someone will find it helpful. First of all, I used array to store current page token, on every page. On "Previous Page" button click, I remove the last element in array. Here's the code:

    
    // Add Previous Page button if there is a previousPageToken
            var previousPageToken = pageTokens[pageTokens.length - 1];
            if (pageTokens.length != 0)
            {
              if (previousPageToken) {
                const previousPageButton = document.createElement('button');
                previousPageButton.textContent = 'Previous Page';
                previousPageButton.classList.add('btn', 'btn-primary', 'previous-page-button');
                previousPageButton.addEventListener('click', function () {
                  pageTokens = pageTokens.slice(0, -1);
                  listFiles(folderId, previousPageToken); // Call listFiles() with the previousPageToken
                });
                document.getElementById('content').appendChild(previousPageButton);
              }
              else if (previousPageToken == null) {
                const previousPageButton = document.createElement('button');
                previousPageButton.textContent = 'Previous Page';
                previousPageButton.classList.add('btn', 'btn-primary', 'previous-page-button');
                previousPageButton.addEventListener('click', function () {
                  pageTokens = [];
                  listFiles(folderId); // Call listFiles()
                });
                document.getElementById('content').appendChild(previousPageButton);
              }
            }
    
            // Add Next Page button if there is a nextPageToken
              const nextPageToken = response.result.nextPageToken;
              if (nextPageToken) {
                const nextPageButton = document.createElement('button');
                nextPageButton.textContent = 'Next Page';
                nextPageButton.classList.add('btn', 'btn-primary', 'next-page-button');
                nextPageButton.addEventListener('click', function () {
                  pageTokens.push(pageToken);
                  listFiles(folderId, nextPageToken); // Call listFiles() with the nextPageToken
                });
    
                document.getElementById('content').appendChild(nextPageButton);
              }
    
    

    Then I've realised, that I can't get first page token for some reason (it was stored as null in array). So I made seperate else if for the case then last element in array is null that meant it was 2nd page. So when I call my function without page token, which on default loads first page. I also made a check if (pageTokens.length != 0) so "Previous Page" button won't render if it is first page.