In node-red how can I have a pagination for a table with amount of elements per page

In node-red I am calling an API and displaying that in a table with sorting but how can I include pagination with amount of elements per page. Below is the code.

<style>
th{
text-align: center;
}
a {
  color:#FFFFFF;
  text-decoration: inherit;
  font-family: Impact, Charcoal, sans-serif;
}
table, th , td  {
  border: 2px solid black;
  border-collapse: collapse;
  padding: 5px;
}
input, select, textarea {
    font-size: 100%;
    width: 98%;
	height: 100%;
}
button{
width:15px;
}
table {
    color: #333;
    font-family: Helvetica, Arial, sans-serif;
    width: 100%;
    border-collapse: collapse;
    border-spacing: 0;
}

td, th {
    
    /* No more visible border */
    height: 30px;
    transition: all 0.3s;
    /* Simple transition for hover effect */
}
th {
    background: #DFDFDF;
    /* Darken header a bit */
    font-weight: bold;
}
td {
    background: #FAFAFA;
}

/* Cells in even rows (2,4,6...) are one color */

tr:nth-child(even) td {
    background: #F1F1F1;
}

/* Cells in odd rows (1,3,5...) are another (excludes header cells)  */

tr:nth-child(odd) td {
    background: #6b6767;
}
tr td:hover {
    background: #666;
    color: #FFF;
}

/* Hover cell effect! */
    
.animate-enter, 
.animate-leave
{ 
    -webkit-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    -moz-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    -ms-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    -o-transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    transition: 400ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
    position: relative;
    display: block;
} 

.animate-enter.animate-enter-active, 
.animate-leave {
    opacity: 1;
    top: 0;
    height: 30px;
}

.animate-leave.animate-leave-active,
.animate-enter {
    opacity: 0;
    top: -50px;
    height: 0px;
}
    
.container
{
    max-height: 450px;
    overflow-y: scroll;
    overflow-x: hidden;
}
</style>

<div>
     <form>
      <span class="input-group">
          <i class="fa fa-search"></i>
        <input type="text" class="form-control" placeholder="Search" ng-model="search">
      </span>      
  </form>
  <div class="container" ng-app="sortApp">

      <table>
        <thead>
        <tr style="width:100%">
            <td>
          <a href="#">
            Index
          </a>
        </td>
        <td>
          <a href="#" ng-click="sortType = 'macId'; sortReverse = !sortReverse">
            macId 
            <span ng-show="sortType == 'macId' && !sortReverse" class="fa fa-caret-down"></span>
            <span ng-show="sortType == 'macId' && sortReverse" class="fa fa-caret-up"></span>
          </a>
        </td>
        <td>
          <a href="#" ng-click="sortType = '(deviceType -0)'; sortReverse = !sortReverse">
          deviceType 
            <span ng-show="sortType == '(deviceType -0)' && !sortReverse" class="fa fa-caret-down"></span>
            <span ng-show="sortType == '(deviceType -0)' && sortReverse" class="fa fa-caret-up"></span>
          </a>
        </td>
        <td>
          <a href="#" ng-click="sortType = 'deviceName'; sortReverse = !sortReverse">
            deviceName
            <span ng-show="sortType == 'deviceName' && !sortReverse" class="fa fa-caret-down"></span>
            <span ng-show="sortType == 'deviceName' && sortReverse" class="fa fa-caret-up"></span>
          </a>
        </td>
		<td>
          <a href="#" ng-click="sortType = 'latitude'; sortReverse = !sortReverse">
            latitude
            <span ng-show="sortType == 'latitude' && !sortReverse" class="fa fa-caret-down"></span>
            <span ng-show="sortType == 'latitude' && sortReverse" class="fa fa-caret-up"></span>
          </a>
        </td>
		<td>
          <a href="#" ng-click="sortType = 'longitude'; sortReverse = !sortReverse">
            longitude
            <span ng-show="sortType == 'longitude' && !sortReverse" class="fa fa-caret-down"></span>
            <span ng-show="sortType == 'longitude' && sortReverse" class="fa fa-caret-up"></span>
          </a>
        </td>
		<td>
          <a href="#" ng-click="sortType = 'updatedTime'; sortReverse = !sortReverse">
            deviceName
            <span ng-show="sortType == 'updatedTime' && !sortReverse" class="fa fa-caret-down"></span>
            <span ng-show="sortType == 'updatedTime' && sortReverse" class="fa fa-caret-up"></span>
          </a>
        </td>

          </tr>
          </thead>
          <tbody>
        <tr ng-repeat="user in msg.options | orderBy:sortType:sortReverse | filter:search track by $index" ng-click="msg.payload = user;send(msg);" style="width:100%" flex>
                <td><b ng-bind="$index+1"></b></td>
				<td ng-bind="user.macId"></td>
               <td ng-bind="user.deviceType"></td>
               <td ng-bind="user.deviceName"></td>
			   <td ng-bind="user.latitude"></td>
			   <td ng-bind="user.longitude"></td>
               <td ng-bind="user.updatedTime"></td>
         </tr>
        </tbody>
      </table>

</div>
</div>

I found one example bu how can I include the libraries http://www.expertphp.in/article/how-to-apply-search-sort-and-pagination-in-angularjs-example-using-dir-pagination-controls

Search the forum for "datatables"
I remember recent post about using that library.

Datatables is a fully featured library that has pagination built in...

https://datatables.net

If I download the necessary libraries and place in the node-red folder can I access using relative path inside ui_template

Honestly, if you are going to these lengths, are you sure that Dashboard is the right tool? Especially if you are resorting to jQuery addins (datatables?) and lots of custom HTML. You probably already know that you can't consume Angular extensions in Dashboard.

This is exactly why I created uibuilder which sorts out all of the serving of the vendor libraries for you, you can add any libraries easily. It also creates a comms channel between the Node-RED back-end server and your front-end browser client code. On the client side, it does all the complex parts of managing the websocket server and presents a very simple event function that lets you easily monitor for new msg's and equally easily send msg's back to Node-RED.

With uibuilder, you could use jQuery alone or you could switch to Vue (or Angular, REACT, MoonJS, etc.). bootstrap-vue has a simple to use datatable component built in and I believe it does paging for you. You simply pass the component an array of objects and some configuration.

I have used the jquery datatable, but in ui_template it is not properly displaying.

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.10.16/datatables.min.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/v/dt/dt-1.10.16/datatables.min.js"></script>
<script>

/* Formatting function for row details - modify as you need */
function format ( d ) {
    // `d` is the original data object for the row
    return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
        '<tr>'+
            '<td>Full name:</td>'+
            '<td>'+d.deviceId+'</td>'+
        '</tr>'+
        '<tr>'+
            '<td>Extension number:</td>'+
            '<td>'+d.cameraId+'</td>'+
        '</tr>'+
        '<tr>'+
            '<td>Extra info:</td>'+
            '<td>And any further details here (images etc)...</td>'+
        '</tr>'+
    '</table>';
}

$(document).ready(function() {
    var table = $('#example').DataTable( {
        "ajax": 'https://api.myjson.com/bins/16lp6',
        scrollY:        250,
    	deferRender:    true,
    	scroller:       true,
        "columns": [
            {
                "class":          'details-control',
                "orderable":      false,
                "data":           null,
                "defaultContent": ''
            },
            { "data": "name" },
            { "data": "position" },
            { "data": "office" },
            { "data": "salary" },
            { "data": "extn", "visible": false }
            
        ],
        "order": [[1, 'asc']]
    } );

    // Add event listener for opening and closing details
    $('#example tbody').on('click', 'td.details-control', function(){
        var tr = $(this).closest('tr');
        var row = table.row( tr );

        if(row.child.isShown()){
            // This row is already open - close it
            row.child.hide();
            tr.removeClass('shown');
        } else {
            // Open this row
            row.child(format(row.data())).show();
            tr.addClass('shown');
        }
    });

    // Handle click on "Expand All" button
    $('#btn-show-all-children').on('click', function(){
        // Enumerate all rows
        table.rows().every(function(){
            // If row has details collapsed
            if(!this.child.isShown()){
                // Open this row
                this.child(format(this.data())).show();
                $(this.node()).addClass('shown');
            }
        });
    });

    // Handle click on "Collapse All" button
    $('#btn-hide-all-children').on('click', function(){
        // Enumerate all rows
        table.rows().every(function(){
            // If row has details expanded
            if(this.child.isShown()){
                // Collapse row details
                this.child.hide();
                $(this.node()).removeClass('shown');
            }
        });
    });
});

</script>
<style>
td.details-control {
    background: url('https://cdn.rawgit.com/DataTables/DataTables/6c7ada53ebc228ea9bc28b1b216e793b1825d188/examples/resources/details_open.png') no-repeat center center;
    cursor: pointer;
}
tr.shown td.details-control {
    background: url('https://cdn.rawgit.com/DataTables/DataTables/6c7ada53ebc228ea9bc28b1b216e793b1825d188/examples/resources/details_close.png') no-repeat center center;
}
</style>
</head>
<body>
<h3><a target="_blank" href="https://www.gyrocode.com/articles/jquery-datatables-how-to-expand-collapse-all-child-rows/">jQuery DataTables: How to expand/collapse all child rows</a> <small>Regular table</small></h3>

<button id="btn-show-all-children" type="button">Expand All</button>
<button id="btn-hide-all-children" type="button">Collapse All</button>
<hr>
<table id="example" class="display" cellspacing="0" width="100%">
    <thead>
        <tr>
				    <th></th>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Salary</th>
        </tr>
    </thead>
    <tfoot>
        <tr>
				    <th></th>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Salary</th>
        </tr>
    </tfoot>
</table>
</body>
</html>

Try this...

[{"id":"2f3649eb.570fe6","type":"ui_template","z":"f052a358.d8f0d","group":"e8366647.01ffa8","name":"","order":0,"width":0,"height":0,"format":"<script>\n\n/* Formatting function for row details - modify as you need */\nfunction format ( d ) {\n // `d` is the original data object for the row\n return '<table cellpadding=\"5\" cellspacing=\"0\" border=\"0\" style=\"padding-left:50px;\">'+\n '<tr>'+\n '<td>Full name:</td>'+\n '<td>'+d.deviceId+'</td>'+\n '</tr>'+\n '<tr>'+\n '<td>Extension number:</td>'+\n '<td>'+d.cameraId+'</td>'+\n '</tr>'+\n '<tr>'+\n '<td>Extra info:</td>'+\n '<td>And any further details here (images etc)...</td>'+\n '</tr>'+\n '</table>';\n}\n\n$(document).ready(function() {\n var table = $('#example').DataTable( {\n \"ajax\": 'https://api.myjson.com/bins/16lp6',\n scrollY: 250,\n \tdeferRender: true,\n \tscroller: true,\n \"columns\": [\n {\n \"class\": 'details-control',\n \"orderable\": false,\n \"data\": null,\n \"defaultContent\": ''\n },\n { \"data\": \"name\" },\n { \"data\": \"position\" },\n { \"data\": \"office\" },\n { \"data\": \"salary\" },\n { \"data\": \"extn\", \"visible\": false }\n \n ],\n \"order\": [[1, 'asc']]\n } );\n\n // Add event listener for opening and closing details\n $('#example tbody').on('click', 'td.details-control', function(){\n var tr = $(this).closest('tr');\n var row = table.row( tr );\n\n if(row.child.isShown()){\n // This row is already open - close it\n row.child.hide();\n tr.removeClass('shown');\n } else {\n // Open this row\n row.child(format(row.data())).show();\n tr.addClass('shown');\n }\n });\n\n // Handle click on \"Expand All\" button\n $('#btn-show-all-children').on('click', function(){\n // Enumerate all rows\n table.rows().every(function(){\n // If row has details collapsed\n if(!this.child.isShown()){\n // Open this row\n this.child(format(this.data())).show();\n $(this.node()).addClass('shown');\n }\n });\n });\n\n // Handle click on \"Collapse All\" button\n $('#btn-hide-all-children').on('click', function(){\n // Enumerate all rows\n table.rows().every(function(){\n // If row has details expanded\n if(this.child.isShown()){\n // Collapse row details\n this.child.hide();\n $(this.node()).removeClass('shown');\n }\n });\n });\n});\n\n</script>\n\n<div >\n \n <button id=\"btn-show-all-children\" type=\"button\">Expand All</button>\n <button id=\"btn-hide-all-children\" type=\"button\">Collapse All</button>\n <hr>\n <table id=\"example\" class=\"display\" cellspacing=\"0\" width=\"100%\">\n <thead>\n <tr>\n \t\t\t\t <th></th>\n <th>Name</th>\n <th>Position</th>\n <th>Office</th>\n <th>Salary</th>\n </tr>\n </thead>\n <tfoot>\n <tr>\n \t\t\t\t <th></th>\n <th>Name</th>\n <th>Position</th>\n <th>Office</th>\n <th>Salary</th>\n </tr>\n </tfoot>\n </table>\n\n \n</div>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":440,"y":160,"wires":[[]]},{"id":"e8366647.01ffa8","type":"ui_group","z":"","name":"Table","tab":"b604a288.9c60a","disp":true,"width":"12","collapse":false},{"id":"b604a288.9c60a","type":"ui_tab","z":"","name":"Data Table","icon":"dashboard","disabled":false,"hidden":false}]

datatable
Simply it is displaying table data not there

Refresh browser