Load More Records on Button Click with Vue.js and PHP

The number of records displays on the page affect the load time of a webpage.

To improve response time you can show limited records at a time using pagination.

There are various types of pagination available.

One of them is a load-more type.

It adds new records at the end when it gets clicked until records are found.

In this tutorial, I show how you can implement load more functionality on your webpage with Vue.js and PHP.

Load More Records on Button Click with Vue.js and PHP


Contents

  1. Table structure
  2. Configuration
  3. HTML
  4. CSS
  5. PHP
  6. Script
  7. Demo
  8. Conclusion

1. Table structure

Create posts table and added some records.

CREATE TABLE `posts` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `content` text NOT NULL,
  `link` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2. Configuration

Create a config.php for the database connection.

Completed Code

<?php

$host = "localhost"; /* Host name */
$user = "root"; /* User */
$password = ""; /* Password */
$dbname = "tutorial"; /* Database name */

$con = mysqli_connect($host, $user, $password,$dbname);
// Check connection
if (!$con) {
  die("Connection failed: " . mysqli_connect_error());
}

3. HTML

Create the layout using <div > and use v-for to loop on posts variable and retrieve data.

Define the click event on <h1 > which call getPosts() method and add v-bind:class="[isFinished ? 'finish' : 'load-more']" to change class according to isFinished value.

Include vue.js and axios.min.js scripts.

You can download the Axios package from here or you can also use CDN (https://unpkg.com/axios/dist/axios.min.js).

The script.js file contains Vue.js code which creates in the Script section.

Completed Code

<!-- CSS -->
<link href='style.css' rel='stylesheet' type='text/css' >

<!-- Posts List -->
<div class="container" id='myapp'>

   <!-- Post -->
   <div class="post" v-for='post in posts'>
      <h2 v-cloak>{{ post.title }}</h2>
      <p v-cloak>
        {{ post.shortcontent }}
      </p>
      <a :href="post.link" class="more" target="_blank" v-cloak>More</a>
   </div>

   <!-- Load More -->
   <h2 v-bind:class="[isFinished ? 'finish' : 'load-more']" @click='getPosts()' v-cloak>{{ buttonText }}</h2>

</div>

<!-- Script -->
<script src="vue.js"></script>
<script src="axios-master/dist/axios.min.js"></script>
<script src="script.js"></script>

4. CSS

Create a new style.css file.

.container{
  width: 55%;
  margin: 0 auto; 
  border: 0px solid black;
  padding: 10px 0px;
}

/* post */
.post{
  width: 97%;
  min-height: 200px;
  padding: 5px;
  border: 1px solid gray;
  margin-bottom: 15px;
}

.post h1{
  letter-spacing: 1px;
  font-weight: normal;
  font-family: sans-serif;
}

.post p{
  letter-spacing: 1px;
  text-overflow: ellipsis;
  line-height: 25px;
}

/* Load more */
.load-more{
  width: 99%;
  background: #15a9ce;
  text-align: center;
  color: white;
  padding: 10px 0px;
  font-family: sans-serif;
}

.load-more:hover{
  cursor: pointer;
}

/* Finish */
.finish{
  width: 99%;
  background: darkgray;
  text-align: center;
  color: white;
  padding: 10px 0px;
  font-family: sans-serif;
}

/* more link */
.more{
  color: blue;
  text-decoration: none;
  letter-spacing: 1px;
  font-size: 16px;
}

[v-cloak] {
  display:none;
}

5. PHP

Create ajaxfile.php.

Read POST row and rowperpage value.

Use these values in the SELECT query to fetch records from posts table.

Loop on the fetched records and initialize $response_arr array.

Return $response_arr in JSON format.

Completed Code

<?php

// configuration
include 'config.php';

$data = json_decode(file_get_contents("php://input"));

$row = $data->row;
$rowperpage = $data->rowperpage;

// Fetch records
$query = 'SELECT * FROM posts LIMIT '.$row.','.$rowperpage;
$result = mysqli_query($con,$query);

$response_arr = array();

while($datarow = mysqli_fetch_assoc($result)){

   $id = $datarow['id'];
   $title = $datarow['title'];
   $content = $datarow['content'];
   $shortcontent = substr($content, 0, 160)."...";
   $link = $datarow['link'];

   $response_arr[] = array(
     'id'=>$id,
     'title'=>$title,
     'shortcontent'=>$shortcontent,
     'content'=>$content,
     'link'=>$link
   );

}

echo json_encode($response_arr);
exit;

6. Script

Create a new script.js file.

Define the following data variables –

  • isFinished – Use this variable to check whether records are available or not.
  • row – Fetch records position. Assigned value 0.
  • rowperpage – Number of records fetch per request. Assigned value 3.
  • buttonText – This is used to change the <h1 > text.
  • posts – Store response from AJAX request.

Create a getPosts method.

Send AJAX POST request to ajaxfile.php where pass row and rowerpage values as data.

On successful callback check response.data is empty is not.

If not empty then update app.row value and check app.posts length. If length returns 0 then directly assign response.data in app.posts otherwise, change buttonText value and loop on response.data to add data in app.posts.

If response.data is empty then assign true to app.isFinished and update app.buttonText value to "No more records available".

Use created option to call getPosts method after instance created.

Completed Code

var app = new Vue({
  el: '#myapp',
  data: {
    isFinished: false,
    row: 0, // Record selction position
    rowperpage: 3, // Number of records fetch at a time
    buttonText: 'Load More',
    posts: ''
  },
  methods: {
    getPosts: function(){

      axios.post('ajaxfile.php', {
        row: this.row, 
        rowperpage: this.rowperpage
      })
      .then(function (response) {

         if(response.data !='' ){

           // Update rowperpage
           app.row+=app.rowperpage;

           var len = app.posts.length;
           if(len > 0){
             app.buttonText = "Loading ...";
             setTimeout(function() {
                app.buttonText = "Load More";

                // Loop on data and push in posts
                for (let i = 0; i < response.data.length; i++){
                   app.posts.push(response.data[i]); 
                } 
             },500);
           }else{
              app.posts = response.data;
           }

         }else{
           app.buttonText = "No more records avaiable.";
           app.isFinished = true;
         }
       });
     }
   },
   created: function(){
      this.getPosts();
   }
})

7. Demo

View Demo


8. Conclusion

I have assigned 3 to rowperpage data variable which you can modify according to requirement.

Pass additional value from Axios request if you want to also filter records and also update the AJAX file accordingly.

If you found this tutorial helpful then don't forget to share.