Load more Node JS and Mongo DB

Load More Button in Node JS and Mongo DB

In this tutorial, we are going to teach you how you can create a “Load more” button in your Node JS and Mongo DB app. “Load more” means that we will be displaying few records, let’s say 5 when the page loads. Then we will display a button which when clicked will fetch the next 5 records. It is similar to the Facebook infinite scroll, where when you reach the end of the page, it automatically fetched the next posts. If you prefer a video tutorial over a textual tutorial, you can find it below:

Setup the Server

Make sure you have installed Node JS and Mongo DB in your system. To view the data in Mongo DB, you will need a software called Mongo DB Compass. That can be installed during Mongo DB installation. Using Mongo DB Compass, create a database named “loadmore_nodejs_mongodb”. Inside this database, you need to create a collection named “users”. Inside this collection, you can add 10 records for testing. I have added the name and age of each user, the ID is automatically generated by Mongo DB.

Then you need to create an empty folder anywhere on your computer. And create a new file inside it named “server.js”. At the same time, open your command prompt or Terminal in this folder. You can run the following command to enter in this folder:

cd "path of folder"

While being inside the folder, run the following command to initialize it as an NPM:

npm init

After that, you need to install some modules using the following command:

npm install express http mongodb ejs express-formidable
  • We will be using express framework.
  • HTTP module will be used to start the server at a specific port.
  • Mongo DB module will be used to connect and interact with the Mongo DB database.
  • EJS will be used to render HTML files.
  • Express formidable will be used to receive HTTP POST values, which we will be sending from AJAX.

If you do not have a nodemon module you can install it with this command:

npm install -g nodemon

Nodemon command helps you to automatically restart the server if there is any change in server.js file. Now in server.js, initialize express framework. Then create an http server object and start the server at port 3000.

// initialize express framework
var express = require("express");
var app = express();
 
// create http server
var http = require("http").createServer(app);

// start the server
http.listen(3000, function () {
    console.log("Server started at port 3000");
});

Run nodemon command to start the server.

nodemon server.js

Connecting Node JS with Mongo DB

Now we need to connect our Node JS Express app with Mongo DB. We have already installed the Mongo DB module. Now we need to include the Mongo DB and Mongo Client objects. Place the following lines in your server.js file before calling the HTTP listen function:

// include mongo DB module
var mongodb = require("mongodb");
var mongoClient = mongodb.MongoClient;

Now after line 10 from previous code, place the following lines to connect with database:

// connect with mongo DB server and database
mongoClient.connect("mongodb://localhost:27017", {
    useUnifiedTopology: true
}, function (error, client) {
    var database = client.db("loadmore_nodejs_mongodb");
    console.log("Database connected.");
});

Display HTML file

Now we need to show an empty table where data will be populated dynamically. We will be using EJS to render the HTML file. First, we need to tell our Express app that we will be using EJS engine. So add the following lines before connecting the HTTP server in server.js:

// set the view engine as EJS for displaying HTML files
app.set("view engine", "ejs");

Now we need to create a GET route which when accessed from browser will display an HTML page. Place the following lines after line 6 from previous code:

// create a GET HTTP route to show page
app.get("/", function (request, result) {
    // render an HTML page
    result.render("index");
});

Now we need to create a folder named “views” and inside this folder, create a file named “index.ejs”. Inside this file, we will create a table, and give an ID to the <tbody> because we will be displaying data dynamically. And also a load more button.

<!-- views/index.ejs -->

<table>
    <thead>
        <tr>
            <th>ID</th>
            <th>Number</th>
            <th>Age</th>
        </tr>
    </thead>

    <tbody id="data"></tbody>
</table>

<button type="button" onclick="getData();">
    Load More
</button>

Now you can access it by entering the following URL in your browser:

http://localhost:3000/

Get Data from Mongo DB

Now we need to fetch data from database in which a way that it will get 2 records each time a button is clicked. But the first 2 records will be fetched when the page loads. So create a script tag and create a variable which will be incremented each time that button is pressed. This variable will be used to skip the records to fetch the next ones.

<script>

    // Starting position to get new records
    var startFrom = 0;

    window.addEventListener("load", function () {
        // Calling the function on page load
        getData();
    });

</script>

Now we need to create that getData() function in index.ejs file. This will send an AJAX request to the route “load-more” with a method POST. We will also attach our startFrom variable with the AJAX object (line 45). When the response is successfully received from server (line 15), it will be in JSON string. So we convert that in Javascript arrays and objects (line 20). Then we are appending the newly fetched data in our tbody tag. And finally, we are incrementing the startFrom variable with the number of records we want to show in each AJAX call.

// This function will be called every time a button pressed 
function getData() {
    // Creating a built-in AJAX object
    var ajax = new XMLHttpRequest();

    // tell the method and URL of request
    ajax.open("POST", "http://localhost:3000/load-more", true);

    // Detecting request state change
    ajax.onreadystatechange = function () {

        // Called when the response is successfully received
        if (this.readyState == 4) {

            if (this.status == 200) {
                // For debugging purpose only
                // console.log(this.responseText);

                // Converting JSON string to Javasript array
                var data = JSON.parse(this.responseText);
                var html = "";
         
                // Appending all returned data in a variable called html
                for (var a = 0; a < data.length; a++) {
                    html += "<tr>";
                        html += "<td>" + data[a]._id + "</td>";
                        html += "<td>" + data[a].name + "</td>";
                        html += "<td>" + data[a].age + "</td>";
                    html += "</tr>";
                }
         
                // Appending the data below old data in <tbody> tag
                document.getElementById("data").innerHTML += html;

                // number of records you want to show per page
                var limit = 2;
         
                // Incrementing the offset so you can get next records when that button is clicked
                startFrom = startFrom + limit;
            }
        }
    };

    var formData = new FormData();
    formData.append("startFrom", startFrom);

    // Actually sending the request
    ajax.send(formData);
}

Now we need to create a POST route in our server.js. Before creating a POST route, we need to tell our Express app that we will be using the Express-Formidable module to get values (e.g. startFrom) from AJAX requests. So paste the following lines before starting HTTP server:

// server.js

// used to get POST field values
var formidable = require("express-formidable");
app.use(formidable());

Now write the following lines after the Mongo DB is connected:

// create a POST HTTP route to get data
app.post("/load-more", async function (request, result) {
 
    // number of records you want to show per page
    var limit = 2;
 
    // get records to skip
    var startFrom = parseInt(request.fields.startFrom);
 
    // get data from mongo DB
    var users = await database.collection("users").find({})
        .sort({ "id": -1 })
        .skip(startFrom)
        .limit(limit)
        .toArray();
 
    // send the response back as JSON
    result.json(users);
});

If you run the code now, you will see 2 records when page loads. On clicking load more button, 2 more records will be fetched and so on.

Styling the Table

At this point, you have successfully create a feature where you can display few records when page loads. And further records when user clicks a “load more” button. But we can give few styles just to make it look good. Following styles will:

  • Give 1 pixel black border to table and all it’s headings and data tags.
  • border-collapse will merge all the borders into one.
  • We are giving padding (distance between border and content) to all headings and data tags.
  • Giving some margin from bottom to the table to have some space between table and load more button.
table, th, td {
    border: 1px solid black;
    border-collapse: collapse;
}
th, td {
    padding: 25px;
}
table {
    margin-bottom: 20px;
}

Infinite Scroll

You can also use an “infinite scroll” like Facebook. Instead of displaying a button to load more data, more data will be fetched when the user scrolled to the bottom. For that, first you need to include jQuery.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

Then you can replace your window onload event listener with the following:

var loadMore = true;

window.addEventListener("load", function () {
    // Calling the function on page load
    getData();

    $(window).bind('scroll', function() {
        if(!loadMore && $(window).scrollTop() >= $('#data').offset().top + $('#data').outerHeight() - window.innerHeight) {
            // console.log('end reached');
            loadMore = true;
            getData();
        }
    });
});

And finally in your ajax.onreadystatechange listener, when you successfully append the data in tbody, keep the infinite scroll working if there are more records.

if (data.length > 0) {
    loadMore = false;
}

If you face any problems, please feel free to contact us.

Leave a Reply

Please disable your adblocker or whitelist this site!