Vue.js Pagination Issue - Current Page Number Beyond Maximum Page Limit

I'm currently working on incorporating pagination into a table showcasing data for Magic: The Gathering cards.

By default, the table displays only 5 items per page, with options to select pages and set the number of results per page at the bottom of the screen. Navigation is facilitated through "Next Page" and "Previous Page" buttons.

const app = new Vue({
  el: "#app",
  data: {
    apiUrl: "https://api.magicthegathering.io/v1/cards",
    cards: [],
    pageNumber: 1,
    resultsPerPage: 5,
    dropdownResultsPerPage: 5,
    increments: [5, 10, 15, 20, 25]
  },
  created: function() {
    var vue = this;
    axios
      .get(this.apiUrl)
      .then(function(data) {
        vue.cards = data.data.cards;
      })
      .catch(function(error) {
        console.log(error);
      });
  },
  computed: {
    startIndex: function() {
      return (this.pageNumber - 1) * this.resultsPerPage;
    },
    endIndex: function() {
      return this.startIndex + this.dropdownResultsPerPage;
    },
    numberOfPages: function() {
      return Math.ceil(this.cards.length / this.dropdownResultsPerPage);
    },
    paginatedData: function() {
      return this.cards.slice(this.startIndex, this.endIndex);
    }
  },
  methods: {
    nextPage: function() {
      this.pageNumber++;
    },
    previousPage: function() {
      this.pageNumber--;
    }
  }
});
body {
  overflow: hidden;
}

#header {
  display: flex;
  position: sticky;
  border-bottom: 1px solid black;
}

#app .content {
  overflow: auto;
  height: 300px;
  position: relative;
}

#pagination: {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  box-shadow: 0px 0px 6px 2px #fafafa;
}

[v-cloak] {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.6.0/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.8/vue.min.js"></script>
<div id="header">
  <h1>MTG Cards</h1>
</div>
<div id="app" v-cloak>
  <div class="content">
    <table>
      <thead>
        <th>Id</th>
        <th>Name</th>
        <th>Mana Cost</th>
      </thead>
      <tbody>
        <tr v-for="(card, index) in paginatedData" :key="index">
          <td>{{ card.id }}</td>
          <td>{{ card.name }}</td>
          <td>{{ card.manaCost }}</td>
        </tr>
      </tbody>
    </table>
  </div>
  <div id="pagination">
    <p>
      Page:
      <select v-model="pageNumber">
        <option v-for="(page, index) in numberOfPages" :key="index" :value="page">
          {{ page }}
        </option>
      </select>
      of {{ numberOfPages }}
      <button @click="previousPage" :disabled="pageNumber == 1">
        Previous
      </button>
      <button @click="nextPage" :disabled="pageNumber >= numberOfPages">
        Next
      </button> |
      <select v-model="dropdownResultsPerPage">
        <option v-for="(increment, index) in increments" :key="index" :value="increment">
          {{ increment }}
        </option>
      </select>
      cards per page
    </p>
  </div>
</div>

Assuming you have set resultsPerPage to 5, giving you a total of 100 pages.

If you navigate to page 5 out of 20 and then change the value of resultsPerPage to 25, the total number of pages changes from 20 to 4. However, as you are already on page 5, the Page Number dropdown does not reflect this change, making navigation confusing.

Is there a way to update the visual page number while keeping the same results displayed in the table?

Answer №1

The issue being encountered is that if the number of results displayed per page is altered, it can cause the current page number to exceed the new total number of pages.

To resolve this issue, it is necessary to adjust the current page number whenever the resultsPerPage value changes to ensure it remains within the bounds of the new total number of pages.

One way to address this is by monitoring the resultsPerPage value and making corresponding adjustments to the pageNumber. Here is an example implementation of this solution:

const app = new Vue({
  el: "#app",
  data: {
    apiUrl: "https://api.magicthegathering.io/v1/cards",
    cards: [],
    pageNumber: 1,
    resultsPerPage: 5,
    dropdownResultsPerPage: 5,
    increments: [5, 10, 15, 20, 25]
  },
  created: function() {
    this.fetchCards();
  },
  watch: {
    dropdownResultsPerPage(newVal, oldVal) {
      const oldStartIndex = (this.pageNumber - 1) * oldVal;
      this.pageNumber = Math.floor(oldStartIndex / newVal) + 1;
      this.resultsPerPage = newVal; // Make sure to update resultsPerPage
    }
  },
  computed: {
    startIndex: function() {
      return (this.pageNumber - 1) * this.resultsPerPage;
    },
    endIndex: function() {
      return this.startIndex + this.resultsPerPage;
    },
    numberOfPages: function() {
      return Math.ceil(this.cards.length / this.resultsPerPage);
    },
    paginatedData: function() {
      return this.cards.slice(this.startIndex, this.endIndex);
    }
  },
  methods: {
    nextPage: function() {
      if (this.pageNumber < this.numberOfPages) {
        this.pageNumber++;
      }
    },
    previousPage: function() {
      if (this.pageNumber > 1) {
        this.pageNumber--;
      }
    },
    fetchCards: function() {
      var vue = this;
      axios
        .get(this.apiUrl)
        .then(function(response) {
          vue.cards = response.data.cards;
        })
        .catch(function(error) {
          console.log(error);
        });
    }
  }
});

A watcher was implemented for dropdownResultsPerPage, so when it changes, the new pageNumber is calculated based on the previous start index to maintain the user's data range consistency. Additionally, the resultsPerPage value is updated accordingly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

It can be rather time-consuming for updates to appear on a custom domain when using Firebase Hosting

I am currently using Vue Js app with the latest versions of Vite and Vue Router. After pushing changes to Firebase Hosting, I noticed that the changes are instantly reflected on the Firebase-provided domain (e.g mycompany.web.app), but it takes several da ...

Can Mongoose handle document arrays editing and version control efficiently?

Currently working on a web application using Node.js and MongoDB/Mongoose, the main model in our project is Record which contains numerous subdocument arrays such as "Comment", "Bookings", and "Subscribers". However, when users click the delete button in ...

Timeout error of 10000ms occurred while using await with Promise.all in Mocha unit tests

Document: index.ts // Default Exported Classes getItemsA() { return Promise.resolve({ // Simulating API call. Mocking for now. success: true, result: [{ itemA: [] }] }); } getItemsB() { return Promise.resolve({ // Simulating API cal ...

Eliminating the bottom border of all buttons, except for the last three buttons in the list, solely using pure JavaScript, unless alternative methods are available

I have 3 sets of buttons, with each set containing 9 buttons stacked in 3 columns inside an ordered list (ol) within list items (li). I have removed the bottom border of the buttons to avoid double borders since they are stacked on top of each other withou ...

"Utilizing the splice method to insert an element at specified indexes within an

const list = [] const obj = { name: '', mobile: '' } _.forEach(errors, (value, key) => { // eslint-disable-next-line no-debugger // debugger const field = key. ...

Customize your payment with a PayPal button tailored to your desired price

I've been tasked with creating a dynamic PayPal button that can receive different values based on user choices. The website has so many options that creating separate buttons for each choice doesn't seem feasible. I've tried researching solu ...

Learn how to access a variable within the Watch function using a directive in Angular framework

I'm new to Angular and encountering some issues with the watch function. I am trying to track changes in a variable inside a controller, and once the value of this variable changes, I want to pass that updated value to a directive. Below is the code ...

Issue with React and Material UI: The Textfield's "onChange" event is not being triggered

I have been attempting to trigger an onchange function when my Textfield is populated, but for some reason the function never seems to be activated. Despite seeing changes triggered by the React devtool plugin in Chrome, I am at a loss. Any suggestions? i ...

jquery ajax function that returns an object when successful

Below is a brief example of an AJAX call wrapped in a function. MyNS.GetStrings = function (successCallback, errorCallback) { var url = serverUrl + "/GetStrings"; $.ajax({ type: "GET", contentType: "application/json; charset=utf-8", dataType: ...

Display a tooltip when the cursor hovers close to a line in D3 visualizations

Currently, I have a D3js line chart with SVG circles added to the points. When users hover over these circles, they can see a tooltip. https://i.sstatic.net/kYpeg.png https://jsfiddle.net/jhynag08/38/ However, I would like the tooltip to appear when user ...

Conceal All Other Divs upon Clicking on a New Div Bearing the Identical Class

I'm having trouble implementing the feature that closes other divs when I click on a new div with the same class. It seems like it should be straightforward, but for some reason, it's not working for me. Here is the link to the fiddle where I&apo ...

Calling a function within another function is not allowed in Typescript

Essentially, I have an Angular Web Page that uploads a file to the server via a POST request, which is then received by my NodeJS app. The issue arises when attempting to retrieve the file path in subirArchivo() and pass it to a function called InsertaPer ...

Send form using AJAX with a callback function

I need help figuring out how to submit a form when a captcha is clicked. I attempted to use my own jQuery function, but unfortunately it's not working. Could someone please take a look at my code and let me know what's wrong with it? Javascript ...

I am unsuccessful in transferring the "side-panel content" to the side panel located on the main menu page

I am facing an issue where I want to pass My left and right Panel to the main menu page (dashboard), but it is not working as expected. The problem arises because the first page that needs to be declared is the login page (/ root) in my case. If I pass it ...

Exploring the concept of utilizing named arguments within Express.js routing

I've searched extensively, but can't seem to find any information on this topic. My goal is to create requests like the following: url/list/message=hello?id=1234 Despite my efforts, I have not come across any resources on how to achieve this us ...

Exploring the functions of JointJS within a Node.js environment

I am a beginner in using JavaScript, JointJS, and Node.js. I am currently working on a Node.js project in WebStorm, and the file structure looks like this: /test /bin www /node_modules /public /routes index.js users.js /views error.jade ...

Automatic button rotation

I managed to set up a button that works on click with a delay, making it semi-automatic. However, I'm struggling with getting it to not pause after just one click. Here's what I have so far: <!DOCTYPE html> <html> <body> &l ...

Invoking an AJAX function that is not inside the document.ready function

I'm having trouble populating a Google Map and here's some of the code I'm using. The ajax request doesn't seem to be working properly. When I put everything inside document.ready() as an anonymous function, it works fine. However, sinc ...

The Material UI slider vanishes the moment I drag it towards the initial element

After moving the Material UI Slider to the initial position, it suddenly vanishes. via GIPHY I've spent 5 hours attempting to locate the source of the issue but have not had any success. ...

ZK: maintaining session connectivity

When I need to redirect to a tel:**** link in ZK and then redirect the user to another page after the call, I encounter a problem. Every time I click on the link, ZK interprets it as leaving the browser, which results in my client session ending automatica ...