Partha Sarathy
Partha Sarathy

Reputation: 3

create pagination for search filter along with sorting table using knockout js

I am creating table with pagination and search filter. We bind table data with search filter, Is the possible to crate search filter in table with pagination. How to create pagination in table, and also perform search filter, along with sorting also.

 function PlayersViewModel() {

    var self = this,x, i, suits;

    /* text field should be empty */
    self.filterText = ko.observable(""); // Text from search field

    //#region Constant Properties
    self.descending = "fa fa-arrow-down";
    self.ascending = "fa fa-arrow-up";
    //#endregion

    self.CurrentPage = ko.observable(1); // Store the current page of the user
    self.DataPerPage = ko.observable(5); // To identify how many data we want to see per page

    //#region Knockout Observables
    // Observable array that represents each column in the table
    self.columns = ko.observableArray([
        { property: "id", header: "ID", type: "number", state: ko.observable("") },
        { property: "name", header: "Name", type: "string", state: ko.observable("") },
        { property: "time", header: "Time", type: "date", state: ko.observable("") },
        { property: "dob", header: "Date of Birth", type: "date", state: ko.observable("") },
        { property: "address", header: "Address", type: "string", state: ko.observable("") },
        { property: "msg", header: "Body", type: "string", state: ko.observable("") }
    ]);

    // Observable array that will be our data
    self.players = ko.observableArray([
       { id: "01", name: "Micky", time: "2015-02-09 4:46:56.678", dob: "10/20/1974", address: "London", msg: "Received Message" },
       { id: "02", name: "Griffey", time: "2015-03-09 4:46:54.678", dob: "11/21/1969", address: "Russia", msg: "Received Message" },
       { id: "03", name: "Derek", time: "2015-01-07 4:46:55.678", dob: "6/26/1931", address: "London", msg: "Send Message" },
       { id: "04", name: "Steven", time: "2015-03-09 4:46:56.678", dob: "2/10/1963", address: "Russia", msg: "Send Message" },
       { id: "05", name: "Jafer", time: "2015-02-09 5:46:56.540", dob: "12/18/1886", address: "London", msg: "Received Message" },
       { id: "06", name: "Jenifer", time: "2015-01-14 4:52:16.379", dob: "11/29/1970", address: "China", msg: "Send Message" },
       { id: "07", name: "Jones", time: "2015-03-08 5:26:33.600", dob: "8/24/1895", address: "London", msg: "Received Message" },
       { id: "08", name: "Micky", time: "2015-02-09 4:46:56.678", dob: "10/20/1974", address: "London", msg: "Received Message" },
       { id: "09", name: "Bruce", time: "2015-03-09 4:46:54.678", dob: "11/21/1969", address: "Russia", msg: "Received Message" },
       { id: "10", name: "Peter", time: "2015-01-07 4:46:55.678", dob: "6/26/1931", address: "London", msg: "Send Message" },
       { id: "11", name: "Wayne", time: "2015-03-09 4:46:56.678", dob: "2/10/1963", address: "Russia", msg: "Send Message" },
       { id: "12", name: "Sam", time: "2015-02-09 5:46:56.540", dob: "12/18/1886", address: "London", msg: "Received Message" },
       { id: "13", name: "Jenifer", time: "2015-01-14 4:52:16.379", dob: "11/29/1970", address: "China", msg: "Send Message" },
       { id: "14", name: "Smith", time: "2015-03-08 5:26:33.600", dob: "8/24/1895", address: "London", msg: "Received Message" }
    ]);
    //#endregion

    /* script for search filter */

    suits = self.players();


    for ( i = 0; i < suits.length; i++) {
        suits[i]["search_content"] = ">";
        for ( x in suits[i] ) {
            if ( !suits[i].hasOwnProperty(x) || x == "search_content" || typeof suits[i][x] !== "string") {continue;}
            suits[i]["search_content"] += suits[i][x].toUpperCase();
        }
    }
    // Collection of players after going through search filter
    self.filteredTestsuites = ko.computed(function () {
        var reg;
        // If many white spaces in a row, replace with only one white space
        fText = self.filterText().replace(/\s+/gi, '|');
        fText = fText.replace(/\|\s*$/gi, '');
        console.log("regex:", fText);
        reg = new RegExp(fText, "gi");
        // If there is anything in the search box, filter for this
        // As of now this does not divide the filterText and only searches the Name field
        var filteredCollection = ko.utils.arrayFilter(self.players(), function(test) {
            if(fText.length)
                return test.search_content.match(reg);
            else
                return 1;
        });

        return filteredCollection;
    }, self);
    /* script Ends with text search */


    /* script for sorting */
    //#region Sorting methods
    self.sortClick = function (column) {
        try {
            // Call this method to clear the state of any columns OTHER than the target
            // so we can keep track of the ascending/descending
            self.clearColumnStates(column);

            // Get the state of the sort type
            if (column.state() === "" || column.state() === self.descending) {
                column.state(self.ascending);
            }
            else {
                column.state(self.descending);
            }

            console.log(column.state());
            console.log(column.type);

            switch (column.type) {
                case "number":
                    self.numberSort(column);
                    break;
                case "date":
                    self.dateSort(column);
                    break;
                case "string":
                default:
                    self.stringSort(column);
                    break;
            }
        }
        catch (err) {
            // Always remember to handle those errors that could occur during a user interaction
            alert(err);
        }
    };

    // Generic sort method for numbers and strings
    self.stringSort = function (column) { // Pass in the column object

        self.players(self.players().sort(function (a, b) {

            // Set strings to lowercase to sort properly
            var playerA = a[column.property].toLowerCase(), playerB = b[column.property].toLowerCase();
            if (playerA < playerB) {
                return (column.state() === self.ascending) ? -1 : 1;
            }
            else if (playerA > playerB) {
                return (column.state() === self.ascending) ? 1 : -1;
            }
            else {
                return 0
            }
        }));
    };

    self.numberSort = function (column) {
        self.players(self.players().sort(function (a, b) {

            var playerA = a[column.property], playerB = b[column.property];
            if (column.state() === self.ascending) {
                return playerA - playerB;
            }
            else {
                return playerB - playerA;
            }
        }));

    };

    // Sort by date
    self.dateSort = function (column) {

        self.players(self.players().sort(function (a, b) {

            if (column.state() === self.ascending) {
                return new Date(a[column.property]) - new Date(b[column.property]);
            }
            else {
                return new Date(b[column.property]) - new Date(a[column.property]);
            }
        }));
    };

    //#region Utility Methods
    self.clearColumnStates = function (selectedColumn) {
        var otherColumns = self.columns().filter(function (col) {
            return col != selectedColumn;
        });

        for (var i = 0; i < otherColumns.length; i++) {
            otherColumns[i].state("");
        }
    };
    /* script Ends for sorting */

};

ko.applyBindings(new PlayersViewModel());

They should perform search filter and sorting in the table correctly, how to create pagination for the sample, they do not affect the search filter and sorting in the table.

Upvotes: 0

Views: 477

Answers (1)

user3297291
user3297291

Reputation: 23397

The basics of pagination using a ko.pureComputed:

const paginatedData = ko.pureComputed(
  () => dataSource().slice(
    currentPage() * pageSize(),
    currentPage() * pageSize() + pageSize()
  )
);

In your specific case, dataSource is filteredTestsuites, currentPage is CurrentPage and pageSize is DataPerPage.

Things to keep in mind: - Fix the lower limit of currentPage to 0 - Fix the upper limit of currentPage to Math.floor(dataSource().length) - Make sure that when the dataSource changes in length (i.e. when filtering), the currentPage is updated to match the new restrictions - Make sure that when pageSize is made larger, the currentPage is updated to match the new restrictions.

const currentPage = ko.observable(0);
const pageSize = ko.observable(5);

const dataSource = ko.observableArray(
  Array.from({ length: 100 }, (_, i) => i)
);

const paginatedData = ko.pureComputed(
  () => dataSource().slice(
    currentPage() * pageSize(),
    currentPage() * pageSize() + pageSize()
  )
);

ko.applyBindings({
  next: () => currentPage(currentPage() + 1),
  prev: () => currentPage(currentPage() - 1),
  currentPage,
  paginatedData
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<ul data-bind="foreach: paginatedData">
  <li data-bind="text: $data"></li>
</ul>

<button data-bind="click: prev">&lt;</button>
<span data-bind="text: currentPage"></span>
<button data-bind="click: next">&gt;</button>

Upvotes: 0

Related Questions