EntityGrid CRUD Workflows
EntityGrid extends DataGrid and adds entity/CRUD integration: service calls, dialogs, routing, permissions, and the standard toolbar buttons. This page walks through the CRUD workflow — how a grid loads, adds, edits, and deletes entities.
The CRUD Flow
- List — the grid's
RemoteViewcalls the list service (e.g.Administration/User/List) to load rows. - Add — clicking the add button opens a new-item dialog.
- Edit — clicking an edit link (or a hash route like
#edit/123) opens an edit dialog. - Save — the dialog calls the save service (
.../Createor.../Update). - Delete — the dialog (or a delete button) calls the delete service (
.../Delete). - Refresh — after a dialog saves or deletes, the grid refreshes to reflect the change.
Service Integration
The grid determines its service from getService(). By default this is derived from the entity type (e.g. Administration.User → Administration/User), but generated grids override it explicitly:
protected override getService() { return UserService.baseUrl; }
The list request is sent to ~/Services/<service>/List (see getServiceUrl() / getServiceMethod()).
Opening Dialogs
The add button calls addButtonClick(), which calls editItem(new Object()). editItem() creates the dialog via createEntityDialog(), loads the entity (or a new instance), and opens it:
protected override editItem(entityOrId: any): void {
this.createEntityDialog(this.getItemType(), dlg => {
var dialog = safeCast(dlg, IEditDialog);
if (dialog != null) {
dialog.load(entityOrId, () => {
dialog.dialogOpen(this.openDialogsAsPanel ?? DataGrid.defaultOptions.openDialogsAsPanel);
});
return;
}
// ...
});
}
The dialog type is resolved by getDialogType(), which looks it up in the DialogTypeRegistry (and can load it lazily).
Routing
EntityGrid handles hash-based routing. When the URL hash is #new or #edit/123, the grid opens the corresponding dialog:
#new— opens a new-item dialog.#edit/123— opens an edit dialog for id123.#SomeType/newor#SomeType/edit/123— for polymorphic item types.
This is wired in the constructor via the handleroute event, and routeDialog() keeps the hash in sync with the open dialog.
Permissions
The grid checks permissions from the row definition to enable/disable actions:
| Method | Permission |
|---|---|
hasInsertPermission() |
getInsertPermission() (row's insertPermission) |
hasUpdatePermission() |
getUpdatePermission() (row's updatePermission) |
hasDeletePermission() |
getDeletePermission() (row's deletePermission) |
For example, the add button is disabled when the user lacks insert permission:
buttons.push({
title: this.getAddButtonCaption(),
action: 'add',
cssClass: 'add-button',
icon: faIcon("plus-circle", "green"),
hotkey: 'alt+n',
onClick: () => { this.addButtonClick(); },
disabled: () => !this.hasInsertPermission() || this.readOnly
});
Toolbar Buttons
getButtons() builds the standard toolbar:
- Add — opens a new-item dialog (disabled without insert permission).
- Refresh — reloads the grid.
- Column Picker — lets users choose visible columns.
- Filter — opens the advanced filter dialog.
createToolbarExtensions() adds the include-deleted toggle (when the row has an is-active/is-deleted property) and the quick search input.
Refreshing After a Dialog Saves
When a dialog saves or deletes, it notifies the grid through SubDialogHelper.bindToDataChange, which calls subDialogDataChange(). This refreshes the grid so the new data appears.
See Also
- EntityGrid (API reference) — the full
EntityGridAPI. - DataGrid (API reference) — the base grid API.
- DataGrid Architecture — how the grid stack fits together.
- Creating and Configuring Grids — building grids step by step.
- EntityDialog and CRUD Workflows — the dialog side of CRUD.
- Authorization and Permissions — permission-based UI.
- Frontend Framework Overview — the three client-side packages and how they fit together.