Contact Record
Account Record
The MainContext component is used to encapsulate one or more RecordContexts, SubGrids, or ManyToManyLookupEditors and coordinates save, refresh, validation, and dirty-state tracking across all of them.
A MainContext can contain any combination of the following child components:
RecordContext — Wraps a single Dataverse record for editing.SubGrid — Displays and manages a collection of related records.ManyToManyLookupEditor — Manages many-to-many relationships.<MainContext>
<RecordContext table="contact" id={contactId}>
<TextEdit columnName="firstname" />
<TextEdit columnName="lastname" />
</RecordContext>
<RecordContext table="account" id={accountId}>
<TextEdit columnName="name" />
</RecordContext>
</MainContext><MainContext>
<RecordContext Record="@_contact">
<TextEdit ColumnName="firstname" />
<TextEdit ColumnName="lastname" />
</RecordContext>
<RecordContext Record="@_account">
<TextEdit ColumnName="name" />
</RecordContext>
</MainContext>Include a SaveContextButton inside a MenuBar to allow users to persist changes. When the save button is clicked, all dirty records across all child components are saved in a single transactional request to Dataverse. If any record fails to save, the entire transaction rolls back and no changes are persisted.
<MainContext>
<MenuBar>
<SaveContextButton />
<RefreshContextButton />
</MenuBar>
<RecordContext table="contact" id={contactId}>
<TextEdit columnName="firstname" />
</RecordContext>
<RecordContext table="account" id={accountId}>
<TextEdit columnName="name" />
</RecordContext>
</MainContext><MainContext>
<MenuBar>
<SaveContextButton />
<RefreshContextButton />
</MenuBar>
<RecordContext Record="@_contact">
<TextEdit ColumnName="firstname" />
</RecordContext>
<RecordContext Record="@_account">
<TextEdit ColumnName="name" />
</RecordContext>
</MainContext>Include a RefreshContextButton to allow users to discard unsaved changes and reload the records from Dataverse. If there are unsaved changes, the user is prompted with a confirmation dialog before the refresh is performed.
By default, the MainContext validates all child components before saving. Set ForceSuccessfulValidationBeforeSave to false to disable this behavior.
<MainContext forceSuccessfulValidationBeforeSave={false}>
<SaveContextButton />
<RecordContext table="account" id={accountId}>
<TextEdit columnName="name" />
</RecordContext>
</MainContext><MainContext ForceSuccessfulValidationBeforeSave="false">
<MenuBar>
<SaveContextButton />
</MenuBar>
<RecordContext Record="@_record">
<TextEdit ColumnName="name" />
</RecordContext>
</MainContext>The MainContext automatically tracks whether any child component has unsaved changes via the IsDirty property. If a user attempts to navigate away from the page while there are unsaved changes, a confirmation dialog is displayed. Set DisableUnsavedChangesWarning to true to suppress this dialog for navigation changes. The warning is always shown when refreshing, regardless of this setting.
<MainContext warnOnUnsavedChanges={false}>
<MenuBar>
<SaveContextButton />
<RefreshContextButton />
</MenuBar>
<RecordContext table="account" id={accountId}>
<TextEdit columnName="name" />
</RecordContext>
</MainContext><MainContext DisableUnsavedChangesWarning="true">
<MenuBar>
<SaveContextButton />
<RefreshContextButton />
</MenuBar>
<RecordContext Record="@_record">
<TextEdit ColumnName="name" />
</RecordContext>
</MainContext>Use the OnBeforeSave callback to run custom logic before the save operation. Set CancelEventArgs.Cancel to true to prevent the save from proceeding.
function MyPage() {
const onBeforeSave = async () => {
// Run custom validation or logic.
// Throw to abort the save:
// throw new Error('Validation failed');
};
return (
<MainContext onBeforeSave={onBeforeSave}>
<SaveContextButton />
<RecordContext table="account" id={accountId}>
<TextEdit columnName="name" />
</RecordContext>
</MainContext>
);
}<MainContext OnBeforeSave="OnBeforeSave">
<MenuBar>
<SaveContextButton />
</MenuBar>
<RecordContext Record="@_record">
<TextEdit ColumnName="name" />
</RecordContext>
</MainContext>
@code {
private async Task OnBeforeSave(CancelEventArgs eventArgs)
{
// Run custom validation or logic
// Cancel the save if needed:
// eventArgs.Cancel = true;
}
}The following example demonstrates a MainContext with two RecordContexts, a MenuBar with save and refresh buttons, and a custom OnBeforeSave handler.
Name | Type | Default | Description |
|---|---|---|---|
ChildContent | RenderFragment? | The child components rendered within this context. | |
DisableUnsavedChangesWarning | bool? | When set to true, the unsaved changes warning dialog is not displayed when navigating away from the page. The warning is always shown when refreshing, regardless of this setting. If not explicitly set, the value is inherited from the parent context. | |
ForceSuccessfulValidationBeforeSave | bool | True | Should a successful validation of the record be performed before allowing the record to be saved. |
IsDirty | bool | False | Indicates whether this context or any registered child has unsaved changes. |
ParentContext | MainContext? | The nearest ancestor MainContext, enabling nested context hierarchies. |
ChildContentDisableUnsavedChangesWarningForceSuccessfulValidationBeforeSaveIsDirtyParentContextName | Type | Description |
|---|---|---|
OnBeforeSave | EventCallback<CancelEventArgs> | Callback called before saving. Allows for cancelling the save operation. |
OnBeforeSaveName | Parameters | Type | Description |
|---|---|---|---|
GetRequests | List<OrganizationRequest> | Collects and returns all pending save requests from this context and its children. | |
RefreshAsync | bool forceRefresh | Task | Refreshes this context and all registered child components. |
ResetState | void | Resets pending changes in this context and all registered children. | |
SaveAsync | bool? refresh | Task<bool> | Save the context and any child contexts (grid, record, etc). |
Validate | bool | Validates this context and all registered child components. |
GetRequestsRefreshAsyncResetStateSaveAsyncValidate