JSFiddle - React, Tailwind, and code Playground

HTML

<link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/jquery.ui/1.10.0/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables_themeroller.css">
<div>
     <h1>KnockOut</h1> 
    <div class="dataTables_wrapper">
        <div class="fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix">
            <div class="dataTables_length">
                <label>Show
                    <select size="1" data-bind="value: pageSize, options: ['10', '25', '50', '100']"></select>entries</label>
            </div>
            <div class="dataTables_filter">
                <label>Search:
                    <input type="text" class="ui-widget-content ui-corner-all" data-bind="value: filterText, valueUpdate:'afterkeydown'"
                    />
                </label>
            </div>
        </div>
        <table class="dataTable">
            <thead>
                <tr role="row">
                    <th class="ui-state-default" data-bind="click: setSortColumn.bind($data, 'name')">
                        <div class="DataTables_sort_wrapper">Name<span class="DataTables_sort_icon css_right ui-icon" data-bind="css: {'ui-icon-triangle-1-n' : sortColumn() == 'name' && sortDir() == 'asc', 'ui-icon-triangle-1-s' : sortColumn() == 'name' && sortDir() == 'desc', 'ui-icon-carat-2-n-s' : sortColumn() != 'name'}"></span>

                        </div>
                    </th>
                    <th class="ui-state-default" data-bind="click: setSortColumn.bind($data, 'address')">
                        <div class="DataTables_sort_wrapper">Address<span class="DataTables_sort_icon css_right ui-icon ui-icon-carat-2-n-s"
                            data-bind="css: {'ui-icon-triangle-1-n' : sortColumn() == 'address' && sortDir() == 'asc', 'ui-icon-triangle-1-s' : sortColumn() == 'address' && sortDir() == 'desc', 'ui-icon-carat-2-n-s' : sortColumn() != 'address'}"></span>

    ...

CSS

.gridStyle {
        border: 1px solid rgb(212, 212, 212);
        width: 100%;
        height: 400px
    }
    .row_selected td {
        background-color: #B0BED9 !important;
    }
    table.dataTable tr:nth-child(odd) {
        background-color: #E2E4FF;
    }
    table.dataTable tr:nth-child(even) {
        background-color: white;
    }
    table.dataTable tr:nth-child(odd) td.sorting_1 {
        background-color: #D3D6FF;
    }
    table.dataTable tr:nth-child(odd) td.sorting_2 {
        background-color: #DADCFF;
    }
    table.dataTable tr:nth-child(odd) td.sorting_3 {
        background-color: #E0E2FF;
    }
    table.dataTable tr:nth-child(even) td.sorting_1 {
        background-color: #EAEBFF;
    }
    table.dataTable tr:nth-child(even) td.sorting_2 {
        background-color: #F2F3FF;
    }
    table.dataTable tr:nth-child(even) td.sorting_3 {
        background-color: #F9F9FF;
    }

JavaScript

ko.utils.stringContains = function (string, contains) {
    if (ko.utils.stringIsNullOrEmpty(string)) return false;
    return string.toString().indexOf(contains) != -1;
};
ko.utils.stringIsNullOrEmpty = function (string) {
    return (typeof string === 'undefined' || string === null || string == '');
}

function TableRow(name, addr, city, state, zip) {
    var self = this;
    self.name = ko.observable(name);
    self.address = ko.observable(addr);
    self.city = ko.observable(city);
    self.state = ko.observable(state);
    self.zip = ko.observable(zip);
    return self;
}

function TableModel(rows) {
    var obj = this;
    obj.items = ko.observableArray(rows);
    obj.selectedItem = ko.observable();
    obj.addRow = function (row) {
        obj.items.push(row);
    };
    obj.filterText = ko.observable();
    obj.filteredItems = ko.computed(function () {
        var items = obj.items();
        var filter = obj.filterText();
        if (!ko.utils.stringIsNullOrEmpty(filter)) {
            items = ko.utils.arrayFilter(items, function (item) {
                return ko.utils.stringContains(item.name(), filter) || ko.utils.stringContains(item.address(), filter) || ko.utils.stringContains(item.city(), filter) || ko.utils.stringContains(item.state(), filter) || ko.utils.stringContains(item.zip(), filter);
            });
            obj.currentPage(1);
        }
        return items;
    });
    obj.pageSize = ko.observable(10);
    obj.currentPage = ko.observable(1);
    obj.totalPages = ko.computed(function () {
        var totalPages = Math.ceil(obj.filteredItems().length / obj.pageSize());
        if (totalPages < obj.currentPage()) obj.currentPage(totalPages);
        return totalPages
    });

    function numberWithCommas(x) {
        return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    }
    obj.pageDisplayText = ko.computed(function () {
        var start = (((obj.currentPage() - 1) * obj.pageSize()) + 1);
        var end = Math.min(start +...