Main Pages — Step 15: JSX Render, MainTable & Optional Features¶
Part of: Main Pages guide See also: Steps 9–14: Selection & Toolbar | Checklist & Types
15. JSX Render¶
return (
<div>
<PageSection hasBodyWrapper={false}>
<TitleLayout
id="my-entities title"
headingLevel="h1"
text="My Entities"
/>
</PageSection>
<PageSection hasBodyWrapper={false} isFilled={false}>
<Flex direction={{ default: "column" }}>
<FlexItem>
<ToolbarLayout toolbarItems={toolbarItems} />
</FlexItem>
<FlexItem style={{ flex: "0 0 auto" }}>
<OuterScrollContainer>
<InnerScrollContainer style={{ height: "55vh", overflow: "auto" }}>
{batchError !== undefined && batchError ? (
<GlobalErrors errors={globalErrors.getAll()} />
) : (
/* Table goes here — see "Table" section below */
)}
</InnerScrollContainer>
</OuterScrollContainer>
</FlexItem>
<FlexItem style={{ flex: "0 0 auto", position: "sticky", bottom: 0 }}>
<PaginationLayout
list={entitiesList}
paginationData={paginationData}
variant={PaginationVariant.bottom}
widgetId="pagination-options-menu-bottom"
/>
</FlexItem>
</Flex>
</PageSection>
{/* Modals */}
<ModalErrors errors={modalErrors.getAll()} dataCy="my-entities-modal-error" />
<AddMyEntityModal
show={showAddModal}
handleModalToggle={() => setShowAddModal(!showAddModal)}
onOpenAddModal={() => setShowAddModal(true)}
onCloseAddModal={() => setShowAddModal(false)}
onRefresh={refreshData}
/>
<DeleteMyEntitiesModal
isOpen={showDeleteModal}
onClose={() => setShowDeleteModal(false)}
elementsToDelete={selectedEntities}
clearSelectedElements={() => clearSelectedEntities()}
columnNames={columnNames}
keyNames={keyNames}
onRefresh={refreshData}
updateIsDeleteButtonDisabled={setIsDeleteButtonDisabled}
updateIsDeletion={setIsDeletion}
/>
</div>
);
};
export default MyEntities;
Table Component¶
New pages must use the MainTable component (src/components/tables/MainTable.tsx). Do not create custom table components (e.g. MyEntitiesTable.tsx) — some older pages (ActiveUsers, Hosts, Netgroups, HBACRules) use custom tables, but that pattern is legacy and should not be followed for new pages.
MainTable is a generic, reusable table component that handles checkboxes, shift+click multi-select, enable/disable status styling, skeleton loading, and linking to detail pages. It is used by DnsZones, Trusts, and all newer pages.
Important: When generating a new main page from scratch, showLink must default to false unless explicitly requested. This prevents linking to a settings/detail page that doesn’t exist yet. Set it to true only when the corresponding <Entity>Tabs/<Entity>Settings components have been implemented.
<MainTable
tableTitle="My entities table"
shownElementsList={entitiesList}
pk="cn" // Primary key field name
keyNames={["cn", "description"]} // Fields to display as columns
columnNames={["Name", "Description"]} // Column header labels
hasCheckboxes={true}
pathname="my-entities" // Route segment (no leading '/')
showTableRows={showTableRows}
showLink={false} // Default to false for new pages (no settings page yet)
elementsData={{
isElementSelectable: isMyEntitySelectable,
selectedElements: selectedEntities,
selectableElementsTable: selectableEntitiesTable,
setElementsSelected: setEntitySelected,
clearSelectedElements: clearSelectedEntities,
}}
buttonsData={{
updateIsDeleteButtonDisabled: setIsDeleteButtonDisabled,
isDeletion,
updateIsDeletion: setIsDeletion,
// Optional for enable/disable pages:
updateIsEnableButtonDisabled: setIsEnableButtonDisabled,
updateIsDisableButtonDisabled: setIsDisableButtonDisabled,
isDisableEnableOp: true,
}}
paginationData={{
selectedPerPage,
updateSelectedPerPage: setSelectedPerPage,
}}
statusElementName="myStatusField" // Optional: field name that determines row disabled styling
/>
Optional Features¶
Contextual Help Panel¶
Used by ActiveUsers, Hosts. Wraps the entire page content.
const [isContextualPanelExpanded, setIsContextualPanelExpanded] = useState(false);
// In the toolbar, pass onClick to HelpTextWithIconLayout:
<HelpTextWithIconLayout
textContent="Help"
onClick={() => setIsContextualPanelExpanded(!isContextualPanelExpanded)}
/>
// Wrap the return JSX:
return (
<ContextualHelpPanel
fromPage="my-entities"
isExpanded={isContextualPanelExpanded}
onClose={() => setIsContextualPanelExpanded(false)}
>
<div>
{/* ...normal page content... */}
</div>
</ContextualHelpPanel>
);