articles

Home / DeveloperSection / Articles / Retrieve Data from RESTFul API and add Paging in knockout.js

Retrieve Data from RESTFul API and add Paging in knockout.js

Retrieve Data from RESTFul API and add Paging in knockout.js

Ashutosh Kumar Verma 88 31-May-2024

Add knockout.js in HTML

To add Knockout.js to an HTML file, you need to include the Knockout.js library in your HTML document.

Example:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Knockout.js Example</title>
   <!-- Include Knockout.js library -->
   <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.2/knockout-min.js"></script>
</head>
<body>
<!-- Your HTML content here -->
<script>
   // Your Knockout.js code here
</script>
</body>
</html>

Make sure to replace "https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.2/knockout-min.js" with the appropriate URL if you are hosting the library yourself or if you are using a different version.

Retrieve Data from RESTful API using knockout.js AJAX

//add jQuery CDN for using AJAX for retrieve data from API <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
// Function to fetch data for the current page
self.fetchData = function () {
    $.ajax({
        url: self.DataUrl(),
        method: "GET",
        dataType: "json",
        success: function (response) {
            self.Data(response); // Populate allData array with fetched data            
        },
        error: function (error) {
            console.log("error: ", error);
        }
    });
};

// Initially fetch all data
self.fetchData();

HTML Code for bind API data

<div class="row row-cols-1 row-cols-md-3 g-4" data-bind="foreach: currentPageData">
    <div class="col">
        <div class="card h-100">
            <div class="card-header">
                <span data-bind="text: id"></span>
            </div>
            <div class="card-body">
                <a class="text-decoration-none" data-bind="attr: {href: $root.DataUrl()+'/' +id}">
                    <p class="card-title fs-5 fw-semibold" data-bind="text: title"></p>
                </a>
                <p class="card-text" data-bind="text: body"></p>
            </div>
        </div>
    </div>
</div>

knockout.js code for adding Paging

self.currentPage = ko.observable(1);
self.itemsPerPage = ko.observable(10);
// Bind the data to the current page
self.currentPageData = ko.observableArray([]);  

// Calculate total pages based on total items and items per page
self.totalPages = ko.observable();

// Function to navigate to the previous page
self.goToPreviousPage = function () {
    if (self.currentPage() > 1) {
        self.currentPage(self.currentPage() - 1);
    }
};

// Function to navigate to the next page
self.goToNextPage = function () {
    if (self.currentPage() < self.totalPages()) {
        self.currentPage(self.currentPage() + 1);
    }
};

// Function to navigate to a specific page
self.goToPage = function (pageNumber) {
    self.currentPage(pageNumber);
};              

// Watch for changes in currentPage and fetch data accordingly
self.currentPage.subscribe(function () {  
    var startIndex = (self.currentPage() - 1) * self.itemsPerPage();    
    var endIndex = startIndex + self.itemsPerPage();          
    self.currentPageData(self.Data().slice(startIndex, endIndex));
});self.currentPage.subscribe(function () { var startIndex = (self.currentPage() - 1) * self.itemsPerPage(); var endIndex = startIndex + self.itemsPerPage(); self.currentPageData(self.Data().slice(startIndex, endIndex)); });

HTML Code for add paging on the webpage

<!-- Pagination controls -->
<nav aria-label="Page navigation">
    <ul class="pagination justify-content-end mt-4">
        <li class="page-item" data-bind="css: {disabled: currentPage() === 1}">
            <a class="page-link" href="#" aria-label="Previous" data-bind="click: goToPreviousPage">
                <span aria-hidden="true">Prev</span>
            </a>
        </li>
        <!-- ko foreach: Array(totalPages()) -->
        <li class="page-item" data-bind="css: {active: $parent.currentPage() === ($index() + 1)}">
            <a class="page-link" href="#" data-bind="text: $index() + 1, click: function() { $parent.goToPage($index() + 1); }"></a>
        </li>
        <!-- /ko -->
        <li class="page-item" data-bind="css: {disabled: currentPage() === totalPages()}">
            <a class="page-link" href="#" aria-label="Next" data-bind="click: goToNextPage">
                <span aria-hidden="true">Next</span>
            </a>
        </li>
    </ul>
</nav>

Finally, bind all the knockout.js code to the webpage using the below code

$(document).ready(function () { 
	ko.applyBindings(new AppViewModel()); 
}); 

Here is the complete code of the above samples

HTML Code

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.1/knockout-latest.min.js"></script>
    <title>Fetch data from RESTful API</title>
</head>

<body>
    <div class="container my-4">
        <div class="row">
            <div class="col-12">
                <div class="row row-cols-1 row-cols-md-3 g-4" data-bind="foreach: currentPageData">
                    <div class="col">
                        <div class="card h-100">
                            <div class="card-header">
                                <span data-bind="text: id"></span>
                            </div>
                            <div class="card-body">
                                <a class="text-decoration-none" data-bind="attr: {href: $root.DataUrl()+'/' +id}">
                                    <p class="card-title fs-5 fw-semibold" data-bind="text: title"></p>
                                </a>
                                <p class="card-text" data-bind="text: body"></p>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- Pagination controls -->
                <nav aria-label="Page navigation">
                    <ul class="pagination justify-content-end mt-4">
                        <li class="page-item" data-bind="css: {disabled: currentPage() === 1}">
                            <a class="page-link" href="#" aria-label="Previous" data-bind="click: goToPreviousPage">
                                <span aria-hidden="true">Prev</span>
                            </a>
                        </li>
                        <!-- ko foreach: Array(totalPages()) -->
                        <li class="page-item" data-bind="css: {active: $parent.currentPage() === ($index() + 1)}">
                            <a class="page-link" href="#"
                                data-bind="text: $index() + 1, click: function() { $parent.goToPage($index() + 1); }"></a>
                        </li>
                        <!-- /ko -->
                        <li class="page-item" data-bind="css: {disabled: currentPage() === totalPages()}">
                            <a class="page-link" href="#" aria-label="Next" data-bind="click: goToNextPage">
                                <span aria-hidden="true">Next</span>
                            </a>
                        </li>
                    </ul>
                </nav>
            </div>
        </div>
    </div>
   </body>
</html>

Js Code:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script>
        function AppViewModel() {
            var self = this;

            self.DataUrl = ko.observable("https://jsonplaceholder.typicode.com/posts");
            self.Data = ko.observableArray([]);
            self.currentPage = ko.observable(1);
            self.itemsPerPage = ko.observable(10);

            //Array variable for Bind the data to the current page
            self.currentPageData = ko.observableArray([]);

            // Function to fetch data for the current page
            self.fetchData = function () {
                $.ajax({
                    url: self.DataUrl(),
                    method: "GET",
                    dataType: "json",
                    success: function (response) {
                        self.Data(response); // Populate allData array with fetched data
                        self.totalPages(Math.ceil(self.Data().length / self.itemsPerPage())); // Update total pages
                        // by default loading first 10 records and show on the page
                        self.currentPageData(self.Data().slice(self.currentPage() - 1, self.itemsPerPage()));
                    },
                    error: function (error) {
                        console.log("error: ", error);
                    }
                });
            };

            // Calculate total pages based on total items and items per page
            self.totalPages = ko.observable();

            // Function to navigate to the previous page
            self.goToPreviousPage = function () {
                if (self.currentPage() > 1) {
                    self.currentPage(self.currentPage() - 1);
                }
            };

            // Function to navigate to the next page
            self.goToNextPage = function () {
                if (self.currentPage() < self.totalPages()) {
                    self.currentPage(self.currentPage() + 1);
                }
            };

            // Function to navigate to a specific page
            self.goToPage = function (pageNumber) {
                self.currentPage(pageNumber);
            };

            // Watch for changes in currentPage and fetch data accordingly
            self.currentPage.subscribe(function () {
                var startIndex = (self.currentPage() - 1) * self.itemsPerPage();
                var endIndex = startIndex + self.itemsPerPage();
                self.currentPageData(self.Data().slice(startIndex, endIndex));
            });

            // Initially fetch all data
            self.fetchData();
        }

        $(document).ready(function () {
            ko.applyBindings(new AppViewModel());
        });
    </script>

 

Output:

Retrieve Data from RESTFul API and add Paging in knockout.js

 


Updated 31-May-2024
Hi! This is Ashutosh Kumar Verma. I am a software developer at MindStick Software Pvt Ltd since 2021. I have added some new and interesting features to the MindStick website like a story section, audio section, and merge profile feature on MindStick subdomains, etc. I love coding and I have good knowledge of SQL Database.

Leave Comment

Comments

Liked By