Back to Abp

React Runtime

docs/en/low-code/react-runtime.md

10.5.013.0 KB
Original Source
json
//[doc-seo]
{
    "Description": "Configure the ABP React Low-Code runtime with configureLowCode, dynamic routes, dynamic menu items, generated pages, filters, forms, and export."
}

React Runtime

Preview: The React low-code runtime is part of the preview Low-Code System. Runtime APIs, generated routes, metadata contracts, and UI behavior may change before general availability.

The React runtime renders low-code pages from backend metadata. Generated low-code React applications include the required package and wiring.

json
{
  "dependencies": {
    "@volo/abp-react-lowcode": "<version>"
  }
}

Configure the Runtime

Call configureLowCode once during React startup. Pass the application's Axios instance, notifications, localization, navigation integration, and optional extension points.

tsx
import {
  configureLowCode,
  LowCodeLocalizationProvider,
} from '@volo/abp-react-lowcode';

function configureLowCodeRuntime(translate?: (key: string, defaultValue: string) => string) {
  configureLowCode({
    axios: api,
    onError: (err) => toast.error(err.message),
    onSuccess: (message) => toast.success(message),
    translate,
    navigate: (path) => router.navigate({ to: path }),
    validators: {
      customRule: (value) => value ? null : 'Value is required.',
    },
  });
}

Wrap the router with LowCodeLocalizationProvider when you want dynamic labels and validation messages to use the application localization pipeline.

tsx
<LowCodeLocalizationProvider translate={translate}>
  <RouterProvider router={router} />
</LowCodeLocalizationProvider>

Add Dynamic Routes

Use createDynamicRoutes in the TanStack Router tree.

tsx
import { createDynamicRoutes } from '@volo/abp-react-lowcode';

const dynamicEntityRoute = createDynamicRoutes(rootRoute, {
  beforeLoad: authGuard,
});

const routeTree = rootRoute.addChildren([
  indexRoute,
  accountRoute,
  identityRoute,
  dynamicEntityRoute,
]);

Runtime pages are then available under:

text
/dynamic/<page-name>
/dynamic/<page-name>/create
/dynamic/<page-name>/edit/<record-id>
/dynamic/<page-name>/<record-id>

createDynamicRoutes also accepts basePath when your application should mount dynamic pages somewhere other than /dynamic.

Generated low-code React templates do not register every possible dynamic page path in TanStack Router's module augmentation. Page names come from backend metadata, so keep dynamic low-code routes out of the static route augmentation or cast the dynamic path inside your router navigation adapter if your application uses strict typed navigation.

Add Dynamic Menu Items

Use useMenuItems to load menu items defined by low-code pages. Merge them with your static route configuration and apply the same permission checks used by the rest of the application.

tsx
import { useMenuItems } from '@volo/abp-react-lowcode';

const { data: dynamicMenuItems } = useMenuItems({
  enabled: isAuthenticated,
});

Each menu item includes its page name, display name, icon, order, grouping information, and children.

Page Types

The runtime includes built-in renderers for these page types:

Page typeRuntime behavior
dataGridSearchable, sortable CRUD grid
kanbanCard board grouped by a configured property
calendarCalendar view using date/time properties
galleryCard/gallery view, optionally image-backed
formStandalone form page
dashboardDashboard rows with chart, list, and number visualizations

The generated data grid page includes:

  • Search
  • Sorting
  • Paging
  • Action menu
  • Create and edit forms
  • Permission-aware commands
  • Display values for lookups
  • File and image fields
  • Export
  • Type-aware filters

Forms

Create and edit forms are rendered from form metadata. Tabs, groups, labels, placeholders, controls, default values, validation rules, conditional form rules, and save actions come from the designer.

The runtime can render forms in a modal or on full pages. Full-page forms use the dynamic create/edit routes and the navigate callback configured in configureLowCode.

Filters

Filters are rendered as an ABP-style advanced filter area. The runtime shows all configured filters and only exposes operator UI where it is useful.

File and image filters use a single Has value concept. The value selector controls whether the filter is applied:

  • All does not add a filter.
  • Yes returns records with a value.
  • No returns records without a value.

The URL keeps the existing lcFilters query parameter shape. The runtime maps user-friendly filter choices to the existing backend FilterType values.

Export

The runtime export button opens a small menu with direct Excel and CSV actions. If the selected page has exportable file or image fields and bundle export is allowed in the Designer, the menu also shows Files (.zip). Direct export uses the current search, sorting, filters, and visible exportable columns from the page definition maintained in the Low-Code Designer. Use Export options when users need a different row, column, or file output scope.

Available options:

OptionBehavior
Rows: all matching recordsExports all records matching the current search, filters, and sorting
Rows: current pageExports only the current page using the runtime skipCount and maxResultCount
Columns: visible exportable columnsExports columns that are both visible and exportable in the current page definition, ordered by Designer export order
Columns: all exportable fieldsExports page fields marked exportable in the Low-Code Designer, including fields that are hidden from the grid, ordered by Designer export order
File/image: file nameWrites the uploaded file name, or an empty value
File/image: metadata columnsWrites file name, content type, size, width, and height columns
File/image: download linksWrites file name, temporary download URL, link expiry, content type, size, width, height, and status columns

Spreadsheet export stays tabular. It does not embed file bytes in cells. Use download-link columns when spreadsheet readers need a controlled way to fetch individual files, or use Files (.zip) when they need the actual file set. ZIP export contains manifest.csv and files under files/{recordId}/{fieldName}/{safeFileName}. The manifest reports missing, malformed, unlinked, skipped, and exported files.

The columns available in the runtime export dialog and their default order are controlled by the page-level Export Fields section in the Low-Code Designer. The runtime cannot use the dialog to bypass non-exportable fields.

The runtime first requests a short-lived token and then calls the Excel, CSV, or ZIP export endpoint. The export token is single-use and is bound to the current page, entity, tenant, child page, and foreign-access context. Temporary file links use separate short-lived tokens bound to the exported record field and blob. Text that looks like a spreadsheet formula is escaped in exported headers and cells. If a caller manually sends a non-exportable field name, the backend rejects the request.

EndpointDescription
GET /api/low-code/pages/{pageName}/download-tokenGets a short-lived token
GET /api/low-code/pages/{pageName}/export/excelDownloads Excel
GET /api/low-code/pages/{pageName}/export/csvDownloads CSV
GET /api/low-code/pages/{pageName}/export/filesDownloads a ZIP with selected file/image fields
GET /api/low-code/pages/export/files/{token}Downloads one temporary file link from spreadsheet link mode

Child and foreign-access pages use the matching /children/{childEntityName} and /foreign-access/{sourceEntityName} page endpoints.

Troubleshooting:

SymptomLikely cause
Invalid or expired download tokenThe token is single-use, expired, or was requested for a different page/context
Export row limit exceededNarrow the filters, export the current page, or increase LowCode:Export:MaxRows
File link expiredRe-run export; temporary file links are intentionally short-lived
File not exported markerThe file was missing, malformed, no longer linked to the exported record, or skipped by ZIP file count/size limits
ZIP bundle export disabledEnable file bundle export for the page in the Low-Code Designer

Files and Attachments

File and image fields use the page file endpoints. Record-level attachments use attachment endpoints when attachments are enabled for the entity.

APIPurpose
uploadPageFileUpload a file/image field value for a page field
downloadPageFileDownload a file/image field value
buildPageFileDownloadUrlBuild a URL for image previews or download links
usePageFileObjectUrlCreate and revoke an object URL for file previews
useEntityAttachmentsLoad record attachments
useUploadEntityAttachmentsUpload one or more attachments
useDeleteEntityAttachmentDelete an attachment
downloadEntityAttachmentDownload an attachment

Uploads are still validated on the backend by the configured file size and content type rules. Downloads are checked against the owning record before returning the blob, and user-provided file names should be treated as display text only. Use usePageFileObjectUrl for previews so object URLs are revoked when the component unmounts.

Hooks and Components

The package exposes hooks for composing custom pages around the same backend API:

APIPurpose
usePageDefinitions, usePageDefinitionLoad page metadata
useFormDefinitionLoad a named runtime form
useDashboardDefinition, useDashboardDataLoad dashboard metadata and data
usePageData, usePageRecordLoad list data and a single record
usePageCreate, usePageUpdate, usePageDeleteMutate records
usePageLookupLoad lookup/autocomplete options
usePageExportExport current list state

The package also exports renderer components such as DynamicPage, DynamicEntityPage, DynamicKanbanRenderer, DynamicCalendarRenderer, DynamicGalleryRenderer, DynamicDashboardRenderer, DynamicFormPageRenderer, DynamicFilters, DynamicEntityForm, and ForeignKeyAutocomplete.

Extension Points

configureLowCode supports these extension points:

OptionPurpose
validatorsCustom validation functions keyed by rule type
pageRenderersOverride built-in page renderers or add new page types
fieldRenderersOverride field rendering by field type or customRenderer
translateResolve low-code localization keys through the application
navigateConnect full-page form navigation to the application router

Custom page renderers receive PageRendererProps. Custom field renderers receive FieldRendererProps.

Runtime API Surface

The React runtime talks to these backend endpoints:

EndpointPurpose
GET /api/low-code/ui/menu-itemsDynamic menu tree
GET /api/low-code/ui/pagesPage list
GET /api/low-code/ui/pages/{pageName}Page summary metadata
GET /api/low-code/ui/pages/{pageName}/ui-definitionRuntime page UI definition
GET /api/low-code/ui/forms/{formName}Runtime form definition
GET /api/low-code/ui/dashboards/{pageName}Dashboard definition
GET /api/low-code/pages/{pageName}/dataPage data with search, filters, sorting, and paging
GET /api/low-code/pages/{pageName}/data/{id}Single page record
POST /api/low-code/pages/{pageName}/dataCreate record
PUT /api/low-code/pages/{pageName}/data/{id}Update record
DELETE /api/low-code/pages/{pageName}/data/{id}Delete record
GET /api/low-code/pages/{pageName}/lookup/{fieldName}Lookup options
POST /api/low-code/pages/{pageName}/files/{fieldName}Upload file/image field
GET /api/low-code/pages/{pageName}/data/{id}/files/{fieldName}/{blobName}Download file/image field
GET /api/low-code/pages/{pageName}/data/{id}/attachmentsList attachments
POST /api/low-code/pages/{pageName}/data/{id}/attachmentsUpload attachment
DELETE /api/low-code/pages/{pageName}/data/{id}/attachments/{attachmentId}Delete attachment
POST /api/low-code/dashboards/{pageName}/dataDashboard visualization data

Troubleshooting

If a generated page does not appear:

  • Confirm the page exists in the designer and has a page name.
  • Confirm the user has the generated page/entity permissions.
  • Confirm createDynamicRoutes is part of the router tree.
  • Confirm useMenuItems is enabled for authenticated users.
  • Confirm the backend host has run migrations and seed data.

If authentication loops back to the login page, check the generated OpenIddict clients and React root URL in appsettings.json.