Validation & lifecycle
| Method | Returns | In short |
|---|---|---|
validateData() | Promise<INgxViewBuilderValidationEvent> | Validate the view on screen, or any structure headlessly |
showToast(payload) | void | Show a toast inside the view |
notifyValidationResult(isValid, issues) | void | Fire onValidated |
notifyComplete(isValid, data, issues) | void | Fire onComplete |
notifySaveRequested(source?) | void | Fire onSaveRequested |
| render notifications | void | Fire the render phases |
notifyTabChanged / notifyCurrentPageChanged / notifyDialogClosed | void | Fire navigation events |
| element interaction notifications | void | Fire repeater, upload, tab and accordion events |
Validating
validateData()
validateData(options?: INgxViewBuilderValidateDataOptions): Promise<INgxViewBuilderValidationEvent>
validateData(structure: IStructure | string, data: Record<string, unknown> | string | null, options?): Promise<INgxViewBuilderValidationEvent>Two ways to call it.
The view on screen. Without a structure, it validates the view the person is filling in, exactly like the built-in Validate button: every rule runs, messages appear under the fields, and onValidating / onValidated fire.
const result = await api.validateData();
if (!result.isValid) {
console.table(result.issues);
return;
}
await save(api.getData());Any structure, headlessly. With a structure and data, it builds a throwaway copy of the view, applies the data, runs expressions and validators, and returns the result. The view on screen is not touched, so you can check stored records, a submission on its way to the server, or a structure that is not rendered at all.
const structure = await firstValueFrom(http.get<IStructure>('/api/views/client'));
const result = await api.validateData(structure, { firstName: '', email: 'not-an-email' });Both return:
{
"isValid": false,
"issues": [
{ "elementName": "firstName", "dataPath": "firstName", "errors": ["This field is required."] },
{ "elementName": "email", "dataPath": "email", "errors": ["Enter a valid email address"] }
]
}Options:
| Option | Default | What it does |
|---|---|---|
emitValidationEvent | true | Fire onValidated with the result. Pass false for a silent check. |
includeHidden | false | Report issues of hidden elements too. |
includeDisabled | false | Report issues of disabled and read-only elements too. |
Validator types you registered and expression functions take part in both modes. For validating on a server, see Headless validation.
Toasts
showToast()
showToast(payload: {
title?: string;
message?: string;
variant?: 'success' | 'info' | 'warning' | 'error';
position?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
autoHide?: boolean;
autoHideMs?: number;
showIcon?: boolean;
icon?: string;
}): voidThe same toast the view's own Toast action shows, styled with its tokens.
api.showToast({ title: 'Saved', message: 'Client HF-20418 was updated.', variant: 'success' });
api.showToast({ title: 'Offline', variant: 'warning', position: 'bottom-center', autoHide: false });Notifications
These fire the events and the automation triggers behind them. The runtime and the builder call them at the right moments; call them yourself when your own code does the equivalent, for example a Save button outside the view.
notifyValidationResult()
notifyValidationResult(isValid: boolean, issues: INgxViewBuilderValidationIssue[]): voidFires onValidating, onValidated and the validated trigger.
notifyComplete()
notifyComplete(isValid: boolean, data: Record<string, unknown>, issues: INgxViewBuilderValidationIssue[]): voidFires onComplete and the completed trigger, what the Submit button does after validating.
const result = await api.validateData();
api.notifyComplete(result.isValid, api.getData(), result.issues);notifySaveRequested()
notifySaveRequested(source: 'header' | 'api' = 'api'): voidFires onSaveRequested with { source, timestamp }, the event the builder's Save button sends.
notifyBeforeRender() / notifyRender() / notifyAfterRender()
notifyBeforeRender(tab: NgxViewBuilderBuilderTabCode): void
notifyRender(tab: NgxViewBuilderBuilderTabCode): void
notifyAfterRender(tab: NgxViewBuilderBuilderTabCode): voidFire onBeforeRender, onRender (with one onElementRender per element) and onAfterRender (with onElementAfterRender). Hosts rarely need them; a reload through setStructure fires them already.
notifyTabChanged()
notifyTabChanged(tab: NgxViewBuilderBuilderTabCode): voidFires onTabChanged with { tab }.
notifyCurrentPageChanged()
notifyCurrentPageChanged(pageIndex: number, pageName: string | null): voidFires onCurrentPageChanged and the pageChanged trigger.
notifyDialogClosed()
notifyDialogClosed(pageIndex: number, pageName: string | null, dialogTitle?: string | null, reason: 'close-button' | 'api' = 'close-button'): voidFires onDialogClosed and the dialogClosed trigger, for a view rendered as a dialog.
Element interaction notifications
notifyDynamicTableRowAdded(element, rowIndex, row?): void
notifyDynamicTableRowRemoved(element, rowIndex, row?): void
notifyDynamicPanelItemAdded(element, rowIndex, row?): void
notifyDynamicPanelItemRemoved(element, rowIndex, row?): void
notifyFileUploadFilesAdded(element, files, addedFiles): void
notifyFileUploadFileRemoved(element, files, removedFile, removedIndex): void
notifyElementTabChanged(element, previousTabValue, tabValue, tabIndex): void
notifyAccordionItemToggled(element, itemIndex, itemValue, expanded): voidThe elements call these when a person adds a row, uploads a file, switches a tab or opens an accordion section, and each fires the event of the same name. element is the element's model; get it with getElementModel. When you change rows from code, use the rows handle, which fires them for you.