When working with Joget DX Form Grids that load 50+ rows, form rendering can slow down noticeably. Because Joget's standard Form Grid uses Handsontable under the hood, rendering every single row on a single screen creates DOM bloat.
In this guide, we'll write a simple JavaScript snippet that hooks into Joget's internal Handsontable instance (FormUtil.getField().data("hot")) to add fast, dynamic client-side pagination with numeric page controls (Prev 1 ... 4 5 6 ... 10 Next).
How It Works
-
Accessing the Hot Instance: Joget stores the underlying Handsontable instance on the jQuery element data key
"hot". We pollFormUtil.getField("your_grid_id")?.data("hot")until it's ready. -
Data Slicing: Instead of feeding all 100+ rows into the DOM grid simultaneously, the script slices the original array (
hotInstance.getSourceData()) into 10-row chunks (rowsPerPage = 10). -
Dynamic Controls: Clicking next, previous, or any page number calls
hotInstance.loadData(pageData)to swap out the visible rows instantly without a page refresh.
The Code
Place a Custom HTML field inside your Joget form (below your Form Grid) and paste the code below. Be sure to replace your_form_grid_field_id with your actual grid ID.
<div id="gridPaginationControls" style="margin-top: 10px; margin-bottom: 10px;">
<button type="button" id="prevGridPage" class="form-button btn">Previous</button>
<span id="gridPageNumbers"></span>
<button type="button" id="nextGridPage" class="form-button btn">Next</button>
</div>
<style>
#gridPaginationControls button {
margin: 2px;
padding: 4px 10px;
font-size: 12px;
}
#gridPaginationControls .activePage {
font-weight: bold;
background-color: #007bff;
color: #ffffff;
border-color: #007bff;
}
#gridPaginationControls .pageDots {
margin: 0 4px;
user-select: none;
}
</style>
<script>
$(document).ready(function () {
const targetGridFieldId = "your_form_grid_field_id";
function setupHandsontablePagination() {
const $gridElem = FormUtil.getField(targetGridFieldId);
const hotInstance = $gridElem ? $gridElem.data("hot") : null;
// Retry if Handsontable hasn't finished initializing yet
if (!hotInstance) {
setTimeout(setupHandsontablePagination, 100);
return;
}
const rowsPerPage = 10;
let currentPage = 1;
const fullDataSet = hotInstance.getSourceData();
const totalRows = fullDataSet.length;
const totalPages = Math.ceil(totalRows / rowsPerPage) || 1;
function displayPage(pageNumber) {
const startIndex = (pageNumber - 1) * rowsPerPage;
const endIndex = startIndex + rowsPerPage;
const pageRows = fullDataSet.slice(startIndex, endIndex);
hotInstance.loadData(pageRows);
currentPage = pageNumber;
refreshControls();
}
function refreshControls() {
$("#prevGridPage").prop("disabled", currentPage === 1);
$("#nextGridPage").prop("disabled", currentPage === totalPages);
let buttonsHtml = "";
function appendButton(p) {
if (p === currentPage) {
buttonsHtml += `<button type="button" class="gridPageBtn activePage" data-page="${p}" disabled>${p}</button>`;
} else {
buttonsHtml += `<button type="button" class="gridPageBtn" data-page="${p}">${p}</button>`;
}
}
if (totalPages <= 7) {
for (let i = 1; i <= totalPages; i++) appendButton(i);
} else {
appendButton(1);
if (currentPage > 3) buttonsHtml += `<span class="pageDots">…</span>`;
const start = Math.max(2, currentPage - 1);
const end = Math.min(totalPages - 1, currentPage + 1);
for (let i = start; i <= end; i++) appendButton(i);
if (currentPage < totalPages - 2) buttonsHtml += `<span class="pageDots">…</span>`;
appendButton(totalPages);
}
$("#gridPageNumbers").html(buttonsHtml);
}
$("#prevGridPage").on("click", function (e) {
e.preventDefault();
if (currentPage > 1) displayPage(currentPage - 1);
});
$("#nextGridPage").on("click", function (e) {
e.preventDefault();
if (currentPage < totalPages) displayPage(currentPage + 1);
});
$(document).on("click", ".gridPageBtn", function (e) {
e.preventDefault();
const selectedPage = parseInt($(this).data("page"), 10);
displayPage(selectedPage);
});
// Load initial page
displayPage(1);
}
setupHandsontablePagination();
});
</script>
Practical Tips
-
Form Submission Sync: Since
getSourceData()returns references to the master dataset, user edits on any paginated page update the underlying master array automatically. -
Adjusting Page Size: Change
rowsPerPage = 10to20or25depending on your form layout requirements.
Top comments (0)