DataGrid
extends BaseComponent
in package
uses
InitializationTrait, FormTrait, HandleTrait, CsvExportTrait, TreeStateTrait, TreeMoveTrait
Generic admin datagrid: a table overview of the records of any Admin manager ({@see Manager}).
Reads data through findAll() (filtering, sorting and paging run in the Api layer via
ApiBridge) and updates or deletes through updateColumns() / delete(). State (page, sort,
search values) lives in persistent parameters, so it survives in the URL without depending on
the presenter.
Usage (columns and actions are passed as ready objects; see PagePresenter):
$grid = $this->dataGridFactory->create();
$grid->setDataSource($this->pageManager)->setIncludes(['translations']);
$grid->addColumn(Column::create('name')->setProperty('translations.name')->setSortable());
$grid->addRowAction(RowAction::create('edit')->setLink(':Admin:System:Page:edit', ['id' => 'id']));
Table of Contents
Constants
- CONFIRM_FIELD : string = '_confirmed'
- POST flag of a confirmed delete; the confirmation modal (`datagrid.js`) adds it, the server deletes nothing without it ({@see HandleTrait::requireDeleteConfirmation()}).
- PER_PAGE_OPTIONS : mixed = [25, 50, 100]
- Page-size choices (header links; "Default" is null).
- TREE_CHILDREN_LIMIT : mixed = 500
- Default cap of children of one parent in a tree; see {@see setTreeChildrenLimit()}.
- TREE_FULL_LIMIT : mixed = 500
- A tree up to this many nodes (within the scope) opens fully expanded on first view, "Expand all" is refused above it, and a non-collapsible tree ({@see setTreeCollapsible()}) behaves as collapsible above it as a safeguard.
- TREE_SESSION_MAX_IDS : mixed = 5000
- At most this many expanded node ids are kept in the session (guard against bloat).
- VIEW_LIST : mixed = 'list'
- VIEW_TREE : mixed = 'tree'
- CSV_BATCH_SIZE : int = 500
- Batch size for reading `findAll()` incrementally.
- CSV_DELIMITER : string = ';'
- Field delimiter: a semicolon (Czech Excel convention), not a comma.
Properties
- $container : Container
- $dir : string|null
- Sort direction `asc`|`desc`.
- $filters : array<string, mixed>
- Values of the search fields keyed by column name. Range stores `['from' => …, 'to' => …]`, multiselect an array of values.
- $orderBy : string|null
- Column name the list is sorted by (click on the heading).
- $page : int
- $perPage : int|null
- User override of rows per page; null means the default (`setItemsPerPage()`).
- $reorder : bool
- "Reorder" mode: switches a tree grid from the flat table (arrows) to the nested drag & drop view ({@see isDragView()}). The user turns it on with a toolbar button; it applies only in the tree view.
- $routerDispatcher : RouterDispatcher
- $translator : ITranslator
- $treeRoot : int|null
- Tree focus: the grid shows only the subtree of the node with this id (children are the first level) and a breadcrumb above it. Persistent so the URL can be shared; the expansion state is kept in the session instead ({@see TreeStateTrait}). null means the whole tree.
- $view : string|null
- Tree grid view: `list` is the flat paged list with a "Path" column (default), `tree` the hierarchy with ▸/▾ and focus. The choice is remembered in the session per grid ({@see TreeStateTrait::isTreeViewChosen()}); null means session / default.
- $appContext : AppContext
- $componentParameters : array<string, mixed>
- $currencyContext : CurrencyContext|null
- $deviceDetector : DeviceDetector|null
- $languageContext : LanguageContext|null
- $localizationContext : LocalizationContext|null
- $settingContext : SettingContext
- $themeContext : ThemeContext|null
- $translatorDomain : string|null
- $addDestination : string|null
- $addParams : array<string, mixed>
- $addPrivilege : string|null
- Privilege key of the "add" button; `null` derives it, `''` never hides. See {@see setAddLink()}.
- $columns : array<string, BaseColumn>
- $csvExportEnabled : bool
- Whether the CSV export button is shown in the grid toolbar; off by default. Enabled by {@see enableCsvExport()}, served by {@see CsvExportTrait::handleCsvExport()}.
- $csvExportFileName : string|null
- $dataSource : Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>>|null
- $defaultFilters : array<string|int, Filter>
- $defaultOrder : array<string, bool>
- $defaultOrderCustomized : bool
- Whether the presenter already overrode the default order; see {@see self::setDefaultOrder()}.
- $deleteMethod : string
- Name of the manager method called by the `delete!` signal ({@see HandleTrait::handleDelete()}) and the group action 'delete' ({@see FormTrait::processGroupAction()}). Defaults to `'delete'` (hard delete).
- $dragDrop : bool
- Drag & drop move of tree nodes; enabled via {@see enableDragDrop()}.
- $dragFlat : bool
- Flat drag mode: SortableJS runs only over the root list of siblings and nested lists (drop targets for changing the parent) are not initialized. For grids that may only reorder, not change the parent (e.g. main parameters).
- $explainedDeleteFailures : array<int, true>
- Delete result codes whose message from the `results` domain is shown to the admin instead of the generic failure message, see {@see explainDeleteFailures()}.
- $explainedUpdateFailures : array<int, true>
- Inline update (toggle, select) result codes whose message from the `results` domain is shown instead of the generic failure, see {@see explainUpdateFailures()}.
- $filterControlNames : array<string, string>|null
- Column => name of its filter control; computed lazily once.
- $groupActions : array<string, GroupAction>
- $highlightId : int|null
- Highlighted row, the target of the "Show in tree" action. The `highlight` parameter is one-shot (not persistent): only the action link carries it, other grid links do not, and the JS removes it from the URL after scrolling the row into view, so a reload does not highlight.
- $includes : array<string|int, string>
- $initialized : bool
- $itemIdentifier : string
- $items : array<int, object>
- $itemsById : array<int, object>
- $itemsPerPage : int
- $moveNode : object|null
- Node being moved in this request (signal or modal submit).
- $moveNotices : array<int, array{key: string, type: string}>
- Messages inside the modal; per request, not a session flash, which would resurface on the next open.
-
$pendingConfirmation
: array{message: ?string, actionLabel: ?string, ids: list
, action: string, fields: list }|null - Delete waiting for confirmation (no flag in the POST): message of the action, record ids, the URL and the POST fields to repeat. `render()` then draws the confirmation page.
- $pickerData : array<string, string>
- $pickerExcludeId : int|null
- Id of the record that cannot be picked (self-reference); its row gets no "Select".
- $pickerExcludeSubtreeLft : int|null
- lft/rgt of the whole subtree that cannot be picked (moving a node under its descendant).
- $pickerExcludeSubtreeRgt : int|null
- $pickerFactory : PickerFactory|null
- $pickerLabelCallback : callable(object): string|null
- $pickerLabelProperty : string|null
- $pickerMode : bool
- Picker mode: the grid serves as a record picker for a foreign form.
- $pickerName : string
- $rowActions : array<string|int, RowAction>
- $rowDecorator : callable(array<int, object> $items): void|null
- Optional decorator of the loaded page of records. It is called once with the whole page (not per row), so it can run one batch query and write the values into `#[Transient]` entity properties via setters. For columns that cannot be computed from one entity (an aggregate over a foreign table, e.g. stock summed over warehouses) without the grid knowing JOIN/GROUP BY.
- $totalCount : int
- $tree : bool
- $treeChildrenLimit : int
- $treeCollapsible : bool
- Collapsible tree (▸/▾, focus, session); `false` means always fully expanded (menu).
- $treeDefaultView : string
- Default view of a tree grid until the user switches it.
- $treeLimitLogged : bool
- The non-collapsible tree safeguard has already logged (render and signal in one request).
- $treeMeta : array<int, array{level: int, parentId: int, hasChildren: bool, expanded: bool, up: bool, down: bool}>
- Metadata of the visible tree nodes ({@see TreeRowsBuilder}).
- $treeMoreAfter : array<int, array<int, array{parentId: int, count: int, level: int}>>
- $treeNested : array<int, array{id: int, children: array, more: int}>
- $treeNodeCount : int|null
- $treeOrderProperty : string
- $treeParentProperty : string
-
$treePaths
: array<int, array{full: string, short: string, segments: list
}> - Paths of the rows of the current flat list page ({@see loadTreePaths()}).
- $treePositionFactory : TreePositionFactory|null
- $treeRightProperty : string|null
- $treeRootMissing : bool
- The focused node from the URL does not exist (deleted or foreign scope); the template shows a notice.
- $treeRootMore : int
- How many children of the view root did not fit under the cap.
- $treeRootNode : object|null
- $treeRootResolved : bool
- $treeScope : array<string, scalar|null>
Methods
- __call() : mixed
- Dispatches `renderXyz()` to `render('Xyz', ...$args)`.
- __construct() : mixed
- addColumn() : self
- addDefaultFilter() : self
- Core filter applied on every load (grid scope).
- addGroupAction() : self
- addRowAction() : self
- buildCellHref() : string|null
- Returns the href the cell content is wrapped in when the column has a link ({@see BaseColumn::setLink()}). Parameters are mapped from row properties. In picker mode links are suppressed because a selection must not leave the modal. When a required parameter ({@see BaseColumn::getLinkRequiredParams()}) is missing (null / ''), no link is generated, a guard against broken links and a crash on a missing id.
- buildRowActionHref() : string
- Row action URL (a presenter link, or a grid signal with the record id).
- buildShowInTreeHref() : string
- Builds the "Show in tree" link: cancels search, ordering and page, focuses the parent of the row (a root means no focus; a non-collapsible tree has no focus) and highlights the row once.
- canMoveNodes() : bool
- Tells whether "Move to..." is offered; same gate as drag and drop (a flat drag must not change the parent).
- canReorder() : bool
- Returns whether the "Reorder" view can be switched on. Drag & drop over a tree outside picker mode is enough; the button is available also with user sorting or a filter (flat table).
- canSortChildren() : bool
- Tells whether "sort children alphabetically" is offered.
- createComponent() : IComponent|null
- enableCsvExport() : self
- Enables the "Export CSV" button in the grid toolbar; opt-in, without the call the grid is unchanged and no export code runs. The export reads the current filter and sort state and all rows (no paging, in batches; see {@see CsvExportTrait}); columns are the visible grid columns (not actions).
- enableDragDrop() : self
- Enables drag & drop move of nodes in a tree grid. Works only when {@see setTreeStructure()} is set and the manager implements {@see \App\Core\Traits\Api\Models\Managers\TreeTrait::moveSubtreeTo()}.
- explainDeleteFailures() : self
- Opts in to showing domain reasons for a rejected delete to the admin (e.g. a job cannot be deleted because it contains invoiced work sheets).
- explainUpdateFailures() : self
- Opts in to showing the domain reason of a refused inline update (e.g. the only default PDF layout cannot be turned off). Same rules as {@see explainDeleteFailures()}: each code needs a `results.<camelCase>` translation in cs/en/sk, generic codes do not belong here.
- getAppContext() : AppContext
- getAttachedPresenter() : Presenter
- Presenter of the grid; the component is always attached during render and signals.
- getBodySnippetNames() : array{string, string}
- Returns the whole body snippet and the area with `row-<id>` rows for the current view.
- getColumn() : BaseColumn|null
- getComponentParameter() : mixed
- Returns a component parameter, or null when it is not set.
- getContainer() : Container
- getCurrencyContext() : CurrencyContext|null
- getDataSource() : Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>>|null
- getFilterControlName() : string
- Returns the form control name of the filter of the given column.
- getHighlightId() : int|null
- getItemId() : int
- Record primary key.
- getItemParentId() : int
- Parent id of a tree node (0 is the real root).
- getItemsPerPage() : int
- Effective rows per page (user override, otherwise the default).
- getLanguageContext() : LanguageContext|null
- getLocalizationContext() : LocalizationContext|null
- getMoveNotices() : array<int, array{key: string, type: string}>
- Returns the messages for the modal; the template translates them by the full grid domain key.
-
getNestedItems()
: array<int, array{item: object, children: array, more: int, meta: array
}> - Returns the list items as a nested tree for the drag & drop template; SortableJS Nested Sortables needs genuine `<ul>/<li>` nesting, not a flat table. Built from the same data as the table ({@see \App\UI\Admin\System\Components\DataGridComponent\Utils\TreeRowsBuilder}); `more` is the number of children above the cap, `meta` the expansion / has-children state.
- getPickerData() : string
- Row data for picking in picker mode; JSON `{key: value}` for `data-pick-data`.
- getPickerLabel() : string
- Row label for picking in picker mode; returned to the opener (hidden + text).
- getRouterDispatcher() : RouterDispatcher
- getRowLabel() : string
- Returns the accessible name of a row for the bulk-action checkbox: same source as {@see getPickerLabel()} (first non-id column / picker label property or callback) but with a different fallback: an empty label becomes "#<id>", never a bare anonymous `ids[]`.
- getSettingContext() : SettingContext
- getSettings() : array<int, array<string, mixed>>
- getThemeContext() : ThemeContext|null
- getTreeLabel() : string
- Returns the node label for breadcrumbs: the value of the indented column, otherwise the picker label.
-
getTreePath()
: array{full: string, short: string, segments: list
}|null - groupActionPrivilege() : string|null
- Returns the privilege that governs the given group action, or null when it has none.
- handleCollapse() : void
- handleCollapseAll() : void
- Collapses everything, also outside the focus (nothing visible there is lost by collapsing).
- handleCsvExport() : void
- handleDelete() : void
- handleDragDrop() : void
- Moves a node in the tree by drag and drop, changing the parent and the position among siblings.
- handleExpand() : void
- handleExpandAll() : void
- Expands the whole current (focused) subtree, only up to {@see DataGrid::TREE_FULL_LIMIT} nodes in total; above it a "focus a smaller branch" message is shown and the state stays unchanged.
- handleInlineUpdate() : void
- handleMoveDown() : void
- handleMoveModal() : void
- Opens the "Move to..." modal for a node (AJAX; without JS it just returns to the list).
- handleMoveUp() : void
- handleRelationToggle() : void
- Toggles a join table link, a {@see RelationColumn} cell (a flag from a related collection picked by `scope`, e.g. a role in the RBAC matrix).
- handleSortChildren() : void
- Sorts the direct children of a parent by label (current language collation) in one operation under the tree lock. `parentId` 0 is the root level of the view (the real roots without focus).
- handleTreeRefresh() : void
- Only redraws the tree body; the JS calls it after a rejected move (`TREE_STALE`) or a parent change.
- hasServiceByType() : bool
- Returns whether the container has a service of the given type.
- initializeAllContexts() : void
- injectDeviceDetector() : void
- isActionAllowed() : bool
- Returns whether the user has the privilege for the given action (`del`, `export`…) in this list.
- isCsvExportEnabled() : bool
- isDeleteAllowed() : bool
- Returns whether the user may delete in this list; one answer for the whole grid.
- isDragDropEnabled() : bool
- isDragFlat() : bool
- Flat drag mode (reordering only, no parent change); see {@see enableDragDrop()}.
- isDragView() : bool
- Returns whether the tree drag & drop view is active: a nested `<ul>/<li>` list with SortableJS Nested Sortables. It requires a tree ({@see canReorder()}) and the user having switched on "Reorder" (persistent `reorder`).
- isPickerMode() : bool
- isPickerSelectable() : bool
- Whether the row can be picked in picker mode (false when excluded, e.g. self-reference or descendant).
- isTreeCollapsible() : bool
- Tells whether the tree can be collapsed.
- isTreePathVisible() : bool
- Tells whether the flat list shows the "Path" column and the "Show in tree" action: only a tree grid with a right bound (ancestors are found from `lft/rgt`) outside the tree view, where indentation and breadcrumbs carry the path.
- isTreeViewChosen() : bool
- Tells whether the tree view is chosen: the `view` URL parameter (stored in the session), otherwise the session, otherwise the grid default. The picker modal (parent selection) and a tree without a right bound ("has children" cannot be told, so always whole) always use the tree.
- loadState() : void
- Validates the persistent parameters from the URL.
- onCreate() : void
-
prepareCell()
: array{template: string, vars: array
, link: ?string, linkTarget: ?string} - Prepares a cell: the column value plus renderer variables for the template `Templates/Default/Cells/<template>.latte`. `link` is the href the template wraps the cell content in ({@see BaseColumn::setLink()}), or null.
- render() : void
- setAddLink() : self
- "Add" button above the table; not shown unless set.
- setAppContext() : $this
- setComponentParameter() : void
- Sets a component parameter.
- setCurrencyContext() : $this
- setDataSource() : self
- Manager the grid reads data from (`findAll()`) and saves changes to.
- setDefaultOrder() : self
- Default list order. The first call drops the built-in `id DESC`, further calls add another level (`setDefaultOrder('type')->setDefaultOrder('name')`).
- setDeleteMethod() : self
- Switches the delete signal and group action to another manager method; see {@see $deleteMethod}.
- setIncludes() : self
- setItemIdentifier() : self
- Property with the record primary key (default `id`).
- setItemsPerPage() : self
- Default rows per page; the user can override it with the 25/50/100 links.
- setLanguageContext() : $this
- setLocalizationContext() : $this
- setPickerData() : self
- Further data carried by the "Select" button (`data-pick-data` JSON); JS spreads it into the opener's fields by the picker `fieldMap`. Fills several fields at once (not only the label), e.g. a user's e-mail and company.
- setPickerExcludeId() : self
- Id of the record that cannot be picked in picker mode (self-reference); its row gets no "Select" button. 0 / null means no exclusion.
- setPickerExcludeSubtree() : self
- lft/rgt range of the subtree that cannot be picked in picker mode. Excludes the root and all descendants (a node cannot be moved under its descendant). The entity must support `getLft()` (duck typing).
- setPickerLabelCallback() : self
- Label for "Select" computed from the whole entity; use it when one property is not enough (empty for some records, or several fields must be combined). Takes precedence over {@see setPickerLabelProperty()}.
- setPickerLabelProperty() : self
- Property for the "Select" button label (what is returned to the opener); defaults to the first non-id column.
- setPickerMode() : self
- Picker mode: the grid serves as a record picker for a foreign form (a modal opened by {@see \App\UI\Admin\System\Components\PickerComponent\Picker}). Hides add, row checkboxes, edit/delete actions and group actions, and gives each row a "Select" action ({@see Templates/Default/Parts/_body.latte}). Filtering, sorting and paging stay; inside the modal they run via AJAX (`picker.js` swaps the dialog body) and the persistent parameter `picker` stays in links because the grid links to `this`.
- setRowDecorator() : self
- Decorator called once after the current page is loaded (see {@see $rowDecorator}).
- setSettingContext() : $this
- setThemeContext() : $this
- setTreeChildrenLimit() : self
- Cap of children of one parent (default {@see TREE_CHILDREN_LIMIT}). Above it the first N children and a row "… N more — use search" are rendered; in "Reorder" a node cannot be dropped at the end of the truncated list (the server would reject the position as TREE_STALE).
- setTreeCollapsible() : self
- Collapsible tree (default `true`): ▸/▾ at the indented column, focus on a subtree, "Expand/Collapse all", expansion state in the session. Data is loaded per parent.
- setTreeDefaultView() : self
- Default view of a tree grid ({@see self::VIEW_LIST} / {@see self::VIEW_TREE}) until the user switches; the choice is then kept in the session.
- setTreeMoveFactories() : self
- Component factories of the modal, injected by {@see \App\UI\Admin\System\Components\DataGridComponent\DataGridFactory}.
- setTreeScope() : self
- Tree scope filter for several trees in one table (e.g. menuItem.menuId). It is added to the list filters (only that tree) and to the move SQL queries (the lft/rgt recalculation does not touch other trees). Empty means a single tree (pages).
- setTreeStructure() : self
- Records form a tree (page, menuItem, category…): the list is ordered depth-first by the order property, indented by level, and rows get arrows to move among siblings.
- setup() : void
- setupAppContext() : void
- sortIdsByLabel() : array<int, int>
- Returns ids sorted by label using `Collator` (`strnatcasecmp` without intl). Equal labels keep their original order (stable sort), so sorting again changes nothing.
- typedComponent() : T
- Returns a subcomponent with a verified type.
- createComponentGridForm() : Form
- createComponentMoveForm() : Form
- createComponentMoveParentPicker() : Picker
- Parent in the modal: a suggest field with the path plus a modal with the same grid in picker mode (without the node and its subtree).
- createComponentMovePosition() : TreePosition
- frontPresenter() : BasePresenter|null
- Returns the front presenter the component is attached to (null outside the front end or when detached).
- getLangId() : int|null
- getTranslator() : ITranslator
- setTemplateFile() : void
- setTranslator() : self
- addFilterControls() : void
- addMoveNotice() : void
- buildMoveTargetParams() : array<string, mixed>
- Builds the redirect parameters after success so that the moved node is highlighted and visible.
-
buildNestedLevel()
: array<int, array{item: object, children: array, more: int, meta: array
}> - buildParentFilter() : Filter
- Builds `parentId IS NULL` (roots) or `= focused node`, plus children of expanded nodes.
- buildStateFilters() : array<string|int, Filter>
- Converts search field values into Core filters via the column filter definitions.
- buildSubtreeFilters() : array<string|int, Filter>
- Returns filters of the focused node subtree (descendants have `lft` inside its bounds); empty without focus.
- buildTreeConfig() : TreeConfig
- `TreeConfig` for the model layer (moves), from the tree configuration and scope.
- buildTreeCrumbs() : array<int, array{id: int|null, label: string}>
- Returns the breadcrumbs of the focused node: ancestors from the bounds (`lft < x and rgt > x`, one query).
- callDeleteMethod() : Result
- Calls the delete method of the manager configured via {@see setDeleteMethod()} (default `'delete'`); the only place that knows its name, shared by the `delete!` signal ({@see HandleTrait::handleDelete()}) and the group action 'delete' ({@see FormTrait::processGroupAction()}).
- confirmDelete() : bool
- Server-side half of the delete confirmation: a delete runs only with the confirmation flag ({@see DataGrid::CONFIRM_FIELD}) in the POST.
- countTreeNodes() : int
- Returns the number of tree nodes within the scope (one count query, cached per request).
- createMultiplierComponent() : Multiplier<string|int, IComponent>
- Creates a multiplier for the component.
- createNewComponentInstance() : IComponent|null
- Creates a new component instance without adding it to the presenter; used by the multiplier.
- createStandardComponent() : IComponent|null
- Creates a standard component (not a multiplier).
- decorateItems() : void
- Calls {@see DataGrid::setRowDecorator()} on the current page when it is set.
- deleteFlashType() : string
- Returns the flash color for {@see deleteResultKey()}; an explained success with a caveat carries the level of its code.
- deleteResultKey() : string
- Returns the flash key for a delete result.
- deleteTreeNodes() : Result
- Deletes nodes of a tree grid in bulk; each node is deleted with its subtree ({@see \App\Core\Traits\Api\Models\Services\TreeTrait::deleteTreeNode()}).
- derivedAddPrivilege() : string|null
- `:Admin:<Module>:<Presenter>:<action>` from the attached presenter; `null` when it cannot be derived.
- filterControlNames() : array<string, string>
- findMoveChildren() : array<int, array{id: int, label: string}>
- findMoveNode() : object|null
- findTreeParentIds() : array<int, int>|null
- Returns ids of nodes with children within the filters, or null when more than {@see DataGrid::TREE_FULL_LIMIT} nodes are in range (expanding all would render too much).
- finishTreeSignal() : void
- Finishes a tree signal: AJAX outside picker redraws the body (plus flash); otherwise it redirects, which `picker.js` follows.
- flashTranslated() : void
- Flashes a message by key; the admin layout translates `{_'//' . $flash->message}`, so the full path including the component domain is needed.
- flattenPost() : array<int, array{0: string, 1: string}>
- Flattens POST data into `name => value` pairs for hidden fields (`ids[]` and nested arrays keep their bracket names); the confirmation flag itself is left out.
- getNodeBounds() : array{int, int}
- getPageCount() : int
- getPaginationSteps() : array<string|int, int>
- Paging steps: the neighborhood of the current page plus evenly spread pages (like {@see \App\UI\Front\System\Components\PaginatorComponent\Paginator}).
- getTreeSessionKey() : string
- State key: presenter, component and scope (each menu has its own).
- getTreeSessionSection() : SessionSection
- hasFilterRow() : bool
- initializeData() : void
- isAddAllowed() : bool
- Returns whether the logged-in user may see the "add" button.
- isExplainedDeleteOutcome() : bool
- isTreeView() : bool
- Tells whether the tree list applies: only in the chosen tree view ({@see TreeStateTrait::isTreeViewChosen()}) and until the user searches or sorts by a column, which breaks the hierarchy and switches the grid to the flat list. The default view is the flat paged list.
- loadExpandedIds() : array<int, int>|null
- loadFlatData() : void
- loadTreeData() : void
- Loads the tree list by parents: one query `parentId IN (root or focused node + expanded)` ordered by `lft`, without paging.
- loadTreePaths() : void
- Loads the ancestors of the flat list page rows in one query within the scope: `lft < max(lft) and rgt > min(rgt) and (lft < l1 and rgt > r1 or ...)`, one pair of bounds per parent ({@see TreePathBuilder::pickQueryBounds()}).
- moveDialogErrorKey() : string
- moveNode() : void
- Moves a node up or down by delegating to the manager model layer ({@see \App\Core\Traits\Shared\Models\Managers\TreeTrait}). The tree configuration (lft/rgt/parent properties and scope) comes from {@see \App\UI\Admin\System\Components\DataGridComponent\DataGrid::buildTreeConfig()}.
- moveResultKey() : string
- Returns the flash key of a move result. A rejected contract (`TREE_STALE`) and a lock (`TREE_LOCKED`) are not plain failures: the user should know to reload or wait a moment.
- prepareTreePathTemplate() : void
- "Path" column and "In tree" action in the flat tree list: the path goes after the indented column (node name), without one after the last column. Row highlighting applies only in the tree.
- prepareTreeTemplate() : void
- Tree variables for the template: row metadata, toggles, focus and breadcrumbs, URLs for JS.
- processGroupAction() : void
- Handles a group action submit: passes the checkbox ids to the action callback; `delete` without a callback deletes through the manager.
- processMoveForm() : void
- processSearch() : void
- Handles the search submit: stores field values in the persistent state and redirects.
- reloadMoveNodeFromForm() : void
- requireDataSource() : Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>>
- Returns the grid manager; signals and actions run after the presenter configured the grid, so a missing data source is a programmer error.
- requireDeletePrivilege() : void
- IMPORTANT: server-side gate for bulk delete, key `…:del`.
- requireEditPrivilege() : void
- IMPORTANT: server-side gate for writes in the grid: inline editing, relation toggles and tree moves.
- requireGroupActionPrivilege() : void
- Gate for any group action; the action declares its own privilege ({@see GroupAction::setPrivilege()}), `delete` has it built in.
- requireOfferedDeletion() : void
- IMPORTANT: server-side delete gate; responds 403 when the grid does not offer deletion in this request.
- requireTreeMoveAllowed() : void
- resolveCollatorLocale() : string
- Returns the collation locale by the admin language (`cs` to `cs_CZ`), Czech by default.
- resolveExpandedIds() : array<int, int>
- Returns the expanded nodes: the session, otherwise the default state (a small tree means all nodes with children).
- resolveMoveNode() : object|null
- Returns the node being moved: from the form value (submit) or from the signal parameter (open).
- resolveMoveParentLabel() : string|null
- resolveOrderBys() : array<string, bool>
- Returns the ordering for `findAll()`; user ordering takes precedence over the default.
- resolveRowLabel() : string
- Shared core of {@see getPickerLabel()} and {@see getRowLabel()}: the first meaningful text of the row.
- resolveTreeLabelProperty() : string|null
- Returns the property of the indented column (node name), which the parent suggest searches by.
- resolveTreeParentId() : int|null
- resolveTreeRootNode() : object|null
- Returns the focused node (`treeRoot`) as an entity, or null for the whole tree.
- rowDeleteConfirmText() : string|null
- Confirmation text of the row delete action (the same the modal shows).
- showMoveModal() : void
- Fills and opens the shared modal with the current form state (idempotent).
- slugifyColumnName() : string
- stateToString() : string
- Converts a persistent state value (mixed, from the URL) to a string for form defaults.
- storeExpandedIds() : void
- stringify() : string
- suggestMoveParents() : array<int, array{id: int, label: string}>
- Suggests parents: LIKE over the name column property, without the node and its subtree, with the path in the label so that equal names can be told apart.
- t() : string
- Translates a key in the component domain.
- updateResultKey() : string
- Returns the flash key for an inline update result; an explained refusal carries the message of its code (absolute key into the `results` domain).
Constants
CONFIRM_FIELD
POST flag of a confirmed delete; the confirmation modal (`datagrid.js`) adds it, the server deletes nothing without it ({@see HandleTrait::requireDeleteConfirmation()}).
public
string
CONFIRM_FIELD
= '_confirmed'
PER_PAGE_OPTIONS
Page-size choices (header links; "Default" is null).
public
mixed
PER_PAGE_OPTIONS
= [25, 50, 100]
TREE_CHILDREN_LIMIT
Default cap of children of one parent in a tree; see {@see setTreeChildrenLimit()}.
public
mixed
TREE_CHILDREN_LIMIT
= 500
TREE_FULL_LIMIT
A tree up to this many nodes (within the scope) opens fully expanded on first view, "Expand all" is refused above it, and a non-collapsible tree ({@see setTreeCollapsible()}) behaves as collapsible above it as a safeguard.
public
mixed
TREE_FULL_LIMIT
= 500
TREE_SESSION_MAX_IDS
At most this many expanded node ids are kept in the session (guard against bloat).
public
mixed
TREE_SESSION_MAX_IDS
= 5000
VIEW_LIST
public
mixed
VIEW_LIST
= 'list'
VIEW_TREE
public
mixed
VIEW_TREE
= 'tree'
CSV_BATCH_SIZE
Batch size for reading `findAll()` incrementally.
private
int
CSV_BATCH_SIZE
= 500
CSV_DELIMITER
Field delimiter: a semicolon (Czech Excel convention), not a comma.
private
string
CSV_DELIMITER
= ';'
Properties
$container
public
Container
$container
Attributes
- #[Inject]
$dir
Sort direction `asc`|`desc`.
public
string|null
$dir
= null
Attributes
- #[Persistent]
$filters
Values of the search fields keyed by column name. Range stores `['from' => …, 'to' => …]`, multiselect an array of values.
public
array<string, mixed>
$filters
= []
Attributes
- #[Persistent]
$orderBy
Column name the list is sorted by (click on the heading).
public
string|null
$orderBy
= null
Attributes
- #[Persistent]
$page
public
int
$page
= 1
Attributes
- #[Persistent]
$perPage
User override of rows per page; null means the default (`setItemsPerPage()`).
public
int|null
$perPage
= null
Attributes
- #[Persistent]
$reorder
"Reorder" mode: switches a tree grid from the flat table (arrows) to the nested drag & drop view ({@see isDragView()}). The user turns it on with a toolbar button; it applies only in the tree view.
public
bool
$reorder
= false
Attributes
- #[Persistent]
$routerDispatcher
public
RouterDispatcher
$routerDispatcher
$translator
public
ITranslator
$translator
Tags
$treeRoot
Tree focus: the grid shows only the subtree of the node with this id (children are the first level) and a breadcrumb above it. Persistent so the URL can be shared; the expansion state is kept in the session instead ({@see TreeStateTrait}). null means the whole tree.
public
int|null
$treeRoot
= null
Attributes
- #[Persistent]
$view
Tree grid view: `list` is the flat paged list with a "Path" column (default), `tree` the hierarchy with ▸/▾ and focus. The choice is remembered in the session per grid ({@see TreeStateTrait::isTreeViewChosen()}); null means session / default.
public
string|null
$view
= null
"Reorder" and the picker modal always load the tree.
Attributes
- #[Persistent]
$appContext
protected
AppContext
$appContext
$componentParameters
protected
array<string, mixed>
$componentParameters
= []
component parameters set by setComponentParameter()
$currencyContext
protected
CurrencyContext|null
$currencyContext
= NULL
$deviceDetector
protected
DeviceDetector|null
$deviceDetector
= NULL
$languageContext
protected
LanguageContext|null
$languageContext
= NULL
$localizationContext
protected
LocalizationContext|null
$localizationContext
= NULL
$settingContext
protected
SettingContext
$settingContext
$themeContext
protected
ThemeContext|null
$themeContext
= NULL
$translatorDomain
protected
string|null
$translatorDomain
= 'admin.system.components.dataGrid'
$addDestination
private
string|null
$addDestination
= null
$addParams
private
array<string, mixed>
$addParams
= []
$addPrivilege
Privilege key of the "add" button; `null` derives it, `''` never hides. See {@see setAddLink()}.
private
string|null
$addPrivilege
= null
$columns
private
array<string, BaseColumn>
$columns
= []
$csvExportEnabled
Whether the CSV export button is shown in the grid toolbar; off by default. Enabled by {@see enableCsvExport()}, served by {@see CsvExportTrait::handleCsvExport()}.
private
bool
$csvExportEnabled
= false
$csvExportFileName
private
string|null
$csvExportFileName
= null
$dataSource
private
Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>>|null
$dataSource
= null
$defaultFilters
private
array<string|int, Filter>
$defaultFilters
= []
filters always applied (grid scope, e.g. menuId)
$defaultOrder
private
array<string, bool>
$defaultOrder
= ['id' => false]
property path => true (asc) / false (desc)
$defaultOrderCustomized
Whether the presenter already overrode the default order; see {@see self::setDefaultOrder()}.
private
bool
$defaultOrderCustomized
= false
$deleteMethod
Name of the manager method called by the `delete!` signal ({@see HandleTrait::handleDelete()}) and the group action 'delete' ({@see FormTrait::processGroupAction()}). Defaults to `'delete'` (hard delete).
private
string
$deleteMethod
= 'delete'
Shop grids (Product/ProductSet) switch to 'softDelete': the manager sets deleted=1
instead of DELETE, so the data stays for old orders. The method must have the same signature
as Manager::delete() (int|array $id): Result).
$dragDrop
Drag & drop move of tree nodes; enabled via {@see enableDragDrop()}.
private
bool
$dragDrop
= false
$dragFlat
Flat drag mode: SortableJS runs only over the root list of siblings and nested lists (drop targets for changing the parent) are not initialized. For grids that may only reorder, not change the parent (e.g. main parameters).
private
bool
$dragFlat
= false
$explainedDeleteFailures
Delete result codes whose message from the `results` domain is shown to the admin instead of the generic failure message, see {@see explainDeleteFailures()}.
private
array<int, true>
$explainedDeleteFailures
= []
ResultCode->value => true
$explainedUpdateFailures
Inline update (toggle, select) result codes whose message from the `results` domain is shown instead of the generic failure, see {@see explainUpdateFailures()}.
private
array<int, true>
$explainedUpdateFailures
= []
ResultCode->value => true
$filterControlNames
Column => name of its filter control; computed lazily once.
private
array<string, string>|null
$filterControlNames
= null
$groupActions
private
array<string, GroupAction>
$groupActions
= []
$highlightId
Highlighted row, the target of the "Show in tree" action. The `highlight` parameter is one-shot (not persistent): only the action link carries it, other grid links do not, and the JS removes it from the URL after scrolling the row into view, so a reload does not highlight.
private
int|null
$highlightId
= null
$includes
private
array<string|int, string>
$includes
= []
include paths for findAll (e.g. ['translations'])
$initialized
private
bool
$initialized
= false
$itemIdentifier
private
string
$itemIdentifier
= 'id'
$items
private
array<int, object>
$items
= []
records of the current page
$itemsById
private
array<int, object>
$itemsById
= []
id => entity of the loaded tree
$itemsPerPage
private
int
$itemsPerPage
= 20
$moveNode
Node being moved in this request (signal or modal submit).
private
object|null
$moveNode
= null
$moveNotices
Messages inside the modal; per request, not a session flash, which would resurface on the next open.
private
array<int, array{key: string, type: string}>
$moveNotices
= []
$pendingConfirmation
Delete waiting for confirmation (no flag in the POST): message of the action, record ids, the URL and the POST fields to repeat. `render()` then draws the confirmation page.
private
array{message: ?string, actionLabel: ?string, ids: list, action: string, fields: list}|null
$pendingConfirmation
= null
$pickerData
private
array<string, string>
$pickerData
= []
data key => property path (fills further fields of the opener)
$pickerExcludeId
Id of the record that cannot be picked (self-reference); its row gets no "Select".
private
int|null
$pickerExcludeId
= null
$pickerExcludeSubtreeLft
lft/rgt of the whole subtree that cannot be picked (moving a node under its descendant).
private
int|null
$pickerExcludeSubtreeLft
= null
$pickerExcludeSubtreeRgt
private
int|null
$pickerExcludeSubtreeRgt
= null
$pickerFactory
private
PickerFactory|null
$pickerFactory
= null
$pickerLabelCallback
private
callable(object): string|null
$pickerLabelCallback
= null
label computed from the entity (takes precedence over the property)
$pickerLabelProperty
private
string|null
$pickerLabelProperty
= null
$pickerMode
Picker mode: the grid serves as a record picker for a foreign form.
private
bool
$pickerMode
= false
$pickerName
private
string
$pickerName
= ''
$rowActions
private
array<string|int, RowAction>
$rowActions
= []
$rowDecorator
Optional decorator of the loaded page of records. It is called once with the whole page (not per row), so it can run one batch query and write the values into `#[Transient]` entity properties via setters. For columns that cannot be computed from one entity (an aggregate over a foreign table, e.g. stock summed over warehouses) without the grid knowing JOIN/GROUP BY.
private
callable(array<int, object> $items): void|null
$rowDecorator
= null
$totalCount
private
int
$totalCount
= 0
$tree
private
bool
$tree
= false
$treeChildrenLimit
private
int
$treeChildrenLimit
= self::TREE_CHILDREN_LIMIT
$treeCollapsible
Collapsible tree (▸/▾, focus, session); `false` means always fully expanded (menu).
private
bool
$treeCollapsible
= true
$treeDefaultView
Default view of a tree grid until the user switches it.
private
string
$treeDefaultView
= self::VIEW_LIST
$treeLimitLogged
The non-collapsible tree safeguard has already logged (render and signal in one request).
private
bool
$treeLimitLogged
= false
$treeMeta
Metadata of the visible tree nodes ({@see TreeRowsBuilder}).
private
array<int, array{level: int, parentId: int, hasChildren: bool, expanded: bool, up: bool, down: bool}>
$treeMeta
= []
$treeMoreAfter
private
array<int, array<int, array{parentId: int, count: int, level: int}>>
$treeMoreAfter
= []
row id => "N more" rows after its subtree
$treeNested
private
array<int, array{id: int, children: array, more: int}>
$treeNested
= []
nesting for the sort view
$treeNodeCount
private
int|null
$treeNodeCount
= null
$treeOrderProperty
private
string
$treeOrderProperty
= 'lft'
$treeParentProperty
private
string
$treeParentProperty
= 'parentId'
$treePaths
Paths of the rows of the current flat list page ({@see loadTreePaths()}).
private
array<int, array{full: string, short: string, segments: list}>
$treePaths
= []
$treePositionFactory
private
TreePositionFactory|null
$treePositionFactory
= null
$treeRightProperty
private
string|null
$treeRightProperty
= 'rgt'
$treeRootMissing
The focused node from the URL does not exist (deleted or foreign scope); the template shows a notice.
private
bool
$treeRootMissing
= false
$treeRootMore
How many children of the view root did not fit under the cap.
private
int
$treeRootMore
= 0
$treeRootNode
private
object|null
$treeRootNode
= null
$treeRootResolved
private
bool
$treeRootResolved
= false
$treeScope
private
array<string, scalar|null>
$treeScope
= []
tree scope filter (property => value); separates trees in one table
Methods
__call()
Dispatches `renderXyz()` to `render('Xyz', ...$args)`.
public
__call(string $name, array<string|int, mixed> $args) : mixed
Called only when the component has no renderXyz() method of its own.
Parameters
- $name : string
- $args : array<string|int, mixed>
__construct()
public
__construct() : mixed
addColumn()
public
addColumn(BaseColumn $column) : self
Parameters
- $column : BaseColumn
Return values
selfaddDefaultFilter()
Core filter applied on every load (grid scope).
public
addDefaultFilter(Filter $filter) : self
Parameters
- $filter : Filter
Return values
selfaddGroupAction()
public
addGroupAction(GroupAction $action) : self
Parameters
- $action : GroupAction
Return values
selfaddRowAction()
public
addRowAction(RowAction $action) : self
Parameters
- $action : RowAction
Return values
selfbuildCellHref()
Returns the href the cell content is wrapped in when the column has a link ({@see BaseColumn::setLink()}). Parameters are mapped from row properties. In picker mode links are suppressed because a selection must not leave the modal. When a required parameter ({@see BaseColumn::getLinkRequiredParams()}) is missing (null / ''), no link is generated, a guard against broken links and a crash on a missing id.
public
buildCellHref(BaseColumn $column, object $entity) : string|null
Parameters
- $column : BaseColumn
- $entity : object
Return values
string|nullbuildRowActionHref()
Row action URL (a presenter link, or a grid signal with the record id).
public
buildRowActionHref(RowAction $action, object $entity) : string
Parameters
- $action : RowAction
- $entity : object
Return values
stringbuildShowInTreeHref()
Builds the "Show in tree" link: cancels search, ordering and page, focuses the parent of the row (a root means no focus; a non-collapsible tree has no focus) and highlights the row once.
public
buildShowInTreeHref(object $entity) : string
In the picker modal it is a plain link that picker.js handles by swapping the modal, like
breadcrumbs.
Parameters
- $entity : object
Return values
stringcanMoveNodes()
Tells whether "Move to..." is offered; same gate as drag and drop (a flat drag must not change the parent).
public
canMoveNodes() : bool
Return values
boolcanReorder()
Returns whether the "Reorder" view can be switched on. Drag & drop over a tree outside picker mode is enough; the button is available also with user sorting or a filter (flat table).
public
canReorder() : bool
Clicking it resets sorting and filter and switches to the clean tree drag view
(render() reorderOnHref).
Return values
boolcanSortChildren()
Tells whether "sort children alphabetically" is offered.
public
canSortChildren() : bool
Return values
boolcreateComponent()
public
createComponent(string $name) : IComponent|null
Parameters
- $name : string
Return values
IComponent|nullenableCsvExport()
Enables the "Export CSV" button in the grid toolbar; opt-in, without the call the grid is unchanged and no export code runs. The export reads the current filter and sort state and all rows (no paging, in batches; see {@see CsvExportTrait}); columns are the visible grid columns (not actions).
public
enableCsvExport(string $fileName) : self
Parameters
- $fileName : string
-
name of the downloaded file (e.g.
'jobs-2026-08-24.csv')
Return values
selfenableDragDrop()
Enables drag & drop move of nodes in a tree grid. Works only when {@see setTreeStructure()} is set and the manager implements {@see \App\Core\Traits\Api\Models\Managers\TreeTrait::moveSubtreeTo()}.
public
enableDragDrop([bool $flat = false ]) : self
The JS logic is in components/tree-drag.js.
Parameters
- $flat : bool = false
-
trueis flat mode (reordering siblings only, no parent change): SortableJS runs only over the root list and nested drop targets stay inactive. For single-level lists (e.g. main parameters) where the parent must not change.
Return values
selfexplainDeleteFailures()
Opts in to showing domain reasons for a rejected delete to the admin (e.g. a job cannot be deleted because it contains invoiced work sheets).
public
explainDeleteFailures(ResultCode ...$codes) : self
Each code needs a translation results.<camelCase> in cs/en/sk. Without the call the grid
shows the generic message. Generic codes (database or API error) do not belong here, their
text tells the admin nothing. It also applies to a success with a caveat (e.g.
PRODUCT_DELETE_HIDDEN, where records were only hidden): the message of the code is shown in
the color of its ResultCode::level() instead of the plain success message.
Parameters
- $codes : ResultCode
Return values
selfexplainUpdateFailures()
Opts in to showing the domain reason of a refused inline update (e.g. the only default PDF layout cannot be turned off). Same rules as {@see explainDeleteFailures()}: each code needs a `results.<camelCase>` translation in cs/en/sk, generic codes do not belong here.
public
explainUpdateFailures(ResultCode ...$codes) : self
Parameters
- $codes : ResultCode
Return values
selfgetAppContext()
public
getAppContext() : AppContext
Return values
AppContextgetAttachedPresenter()
Presenter of the grid; the component is always attached during render and signals.
public
getAttachedPresenter() : Presenter
Return values
PresentergetBodySnippetNames()
Returns the whole body snippet and the area with `row-<id>` rows for the current view.
public
getBodySnippetNames() : array{string, string}
The table and the sort view have separate names in DataGrid.latte (Latte does not allow the
same name in two branches). IMPORTANT: invalidate only what is drawn; otherwise
SnippetRuntime would also render a block from the branch that is not rendered.
Return values
array{string, string} —[body snippet, rows area]
getColumn()
public
getColumn(string $name) : BaseColumn|null
Parameters
- $name : string
Return values
BaseColumn|nullgetComponentParameter()
Returns a component parameter, or null when it is not set.
public
getComponentParameter(string $name) : mixed
Parameters
- $name : string
getContainer()
public
getContainer() : Container
Return values
ContainergetCurrencyContext()
public
getCurrencyContext() : CurrencyContext|null
Return values
CurrencyContext|nullgetDataSource()
public
getDataSource() : Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>>|null
Return values
Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>>|nullgetFilterControlName()
Returns the form control name of the filter of the given column.
public
getFilterControlName(string $column) : string
Nette allows only [a-zA-Z0-9_] in a component name while a column can be a dotted relation
path (status.id), so other characters are replaced by an underscore. A collision after the
conversion (status.id vs status_id) is resolved by a numeric suffix, which keeps the
name unique within the grid.
Parameters
- $column : string
Return values
stringgetHighlightId()
public
getHighlightId() : int|null
Return values
int|nullgetItemId()
Record primary key.
public
getItemId(object $entity) : int
Parameters
- $entity : object
Return values
intgetItemParentId()
Parent id of a tree node (0 is the real root).
public
getItemParentId(object $entity) : int
Parameters
- $entity : object
Return values
intgetItemsPerPage()
Effective rows per page (user override, otherwise the default).
public
getItemsPerPage() : int
Return values
intgetLanguageContext()
public
getLanguageContext() : LanguageContext|null
Return values
LanguageContext|nullgetLocalizationContext()
public
getLocalizationContext() : LocalizationContext|null
Return values
LocalizationContext|nullgetMoveNotices()
Returns the messages for the modal; the template translates them by the full grid domain key.
public
getMoveNotices() : array<int, array{key: string, type: string}>
Return values
array<int, array{key: string, type: string}>getNestedItems()
Returns the list items as a nested tree for the drag & drop template; SortableJS Nested Sortables needs genuine `<ul>/<li>` nesting, not a flat table. Built from the same data as the table ({@see \App\UI\Admin\System\Components\DataGridComponent\Utils\TreeRowsBuilder}); `more` is the number of children above the cap, `meta` the expansion / has-children state.
public
getNestedItems() : array<int, array{item: object, children: array, more: int, meta: array}>
Return values
array<int, array{item: object, children: array, more: int, meta: arraygetPickerData()
Row data for picking in picker mode; JSON `{key: value}` for `data-pick-data`.
public
getPickerData(object $entity) : string
Parameters
- $entity : object
Return values
stringgetPickerLabel()
Row label for picking in picker mode; returned to the opener (hidden + text).
public
getPickerLabel(object $entity) : string
Parameters
- $entity : object
Return values
stringgetRouterDispatcher()
public
getRouterDispatcher() : RouterDispatcher
Return values
RouterDispatchergetRowLabel()
Returns the accessible name of a row for the bulk-action checkbox: same source as {@see getPickerLabel()} (first non-id column / picker label property or callback) but with a different fallback: an empty label becomes "#<id>", never a bare anonymous `ids[]`.
public
getRowLabel(object $entity) : string
Parameters
- $entity : object
Return values
stringgetSettingContext()
public
getSettingContext() : SettingContext
Return values
SettingContextgetSettings()
public
getSettings() : array<int, array<string, mixed>>
Return values
array<int, array<string, mixed>>getThemeContext()
public
getThemeContext() : ThemeContext|null
Return values
ThemeContext|nullgetTreeLabel()
Returns the node label for breadcrumbs: the value of the indented column, otherwise the picker label.
public
getTreeLabel(object $entity) : string
Parameters
- $entity : object
Return values
stringgetTreePath()
public
getTreePath(object $entity) : array{full: string, short: string, segments: list}|null
Parameters
- $entity : object
Return values
array{full: string, short: string, segments: listrow path; null for a root (no ancestors)
groupActionPrivilege()
Returns the privilege that governs the given group action, or null when it has none.
public
groupActionPrivilege(GroupAction $action) : string|null
delete has del built in (deleting is deleting, whoever registers it); other actions
declare theirs via GroupAction::setPrivilege(). An action without a privilege is
guarded only by registration and CSRF.
Parameters
- $action : GroupAction
Return values
string|nullhandleCollapse()
public
handleCollapse(int $id) : void
Parameters
- $id : int
handleCollapseAll()
Collapses everything, also outside the focus (nothing visible there is lost by collapsing).
public
handleCollapseAll() : void
handleCsvExport()
public
handleCsvExport() : void
handleDelete()
public
handleDelete(int $id) : void
Parameters
- $id : int
Attributes
- #[Requires]
- $methods: 'POST'
handleDragDrop()
Moves a node in the tree by drag and drop, changing the parent and the position among siblings.
public
handleDragDrop(int $dragId, int|null $newParentId, int $afterId[, int|null $oldParentId = null ][, int|null $prevId = null ][, int|null $nextId = null ]) : void
afterId: -1 inserts as the first child of newParent, 0 as the last child, >0 after the
sibling with that id.
Neighbor contract: when the client sends prevId/nextId (and oldParentId, 0 for a
root), the server verifies under the tree lock that the node is still under oldParentId
and that prevId/nextId are the current neighbors under newParentId. The position is
then derived from prevId and afterId is ignored: prevId -1 means the start, 0 the end
without neighbor verification (collapsed target), >0 after that node; nextId 0 means
nothing after it, >0 before that node. Without them afterId applies.
The AJAX response is {success: true} or {success: false, code: '<ResultCode name>'}
(TREE_STALE when the tree changed meanwhile, TREE_LOCKED on a concurrent operation);
the JS shows a message by the code and reloads the list. Non-AJAX uses a redirect with a flash.
Calls TreeTrait::moveSubtreeTo().
Parameters
- $dragId : int
- $newParentId : int|null
- $afterId : int
- $oldParentId : int|null = null
- $prevId : int|null = null
- $nextId : int|null = null
Attributes
- #[Requires]
- $methods: 'POST'
handleExpand()
public
handleExpand(int $id) : void
Parameters
- $id : int
handleExpandAll()
Expands the whole current (focused) subtree, only up to {@see DataGrid::TREE_FULL_LIMIT} nodes in total; above it a "focus a smaller branch" message is shown and the state stays unchanged.
public
handleExpandAll() : void
handleInlineUpdate()
public
handleInlineUpdate(int $id, string $column, string $value) : void
Parameters
- $id : int
- $column : string
- $value : string
Attributes
- #[Requires]
- $methods: 'POST'
handleMoveDown()
public
handleMoveDown(int $id) : void
Parameters
- $id : int
Attributes
- #[Requires]
- $methods: 'POST'
handleMoveModal()
Opens the "Move to..." modal for a node (AJAX; without JS it just returns to the list).
public
handleMoveModal(int $id) : void
Parameters
- $id : int
handleMoveUp()
public
handleMoveUp(int $id) : void
Parameters
- $id : int
Attributes
- #[Requires]
- $methods: 'POST'
handleRelationToggle()
Toggles a join table link, a {@see RelationColumn} cell (a flag from a related collection picked by `scope`, e.g. a role in the RBAC matrix).
public
handleRelationToggle(int $id, string $scope, string $column, string $value) : void
The value cannot be stored via updateColumns() (it would write a row column, not the join
row with a composite key), so it delegates to a data source implementing RelationTogglable.
Parameters
- $id : int
- $scope : string
- $column : string
- $value : string
Attributes
- #[Requires]
- $methods: 'POST'
handleSortChildren()
Sorts the direct children of a parent by label (current language collation) in one operation under the tree lock. `parentId` 0 is the root level of the view (the real roots without focus).
public
handleSortChildren([int $parentId = 0 ]) : void
Parameters
- $parentId : int = 0
Attributes
- #[Requires]
- $methods: 'POST'
handleTreeRefresh()
Only redraws the tree body; the JS calls it after a rejected move (`TREE_STALE`) or a parent change.
public
handleTreeRefresh() : void
hasServiceByType()
Returns whether the container has a service of the given type.
public
hasServiceByType(string $className) : bool
The name is composed dynamically (module plus component), so class_exists() runs first, and
a true result guarantees a valid type.
Parameters
- $className : string
Tags
Return values
boolinitializeAllContexts()
public
initializeAllContexts() : void
injectDeviceDetector()
public
injectDeviceDetector(DeviceDetector $detector) : void
Parameters
- $detector : DeviceDetector
isActionAllowed()
Returns whether the user has the privilege for the given action (`del`, `export`…) in this list.
public
isActionAllowed(string $action) : bool
The key is built from the presenter, :Admin:<Module>:<Presenter>:<action>, the same
convention as everywhere in the admin.
IMPORTANT: uses lookup(..., false), not getPresenter(): an unattached component would get
InvalidStateException instead of an answer. Without a presenter the key cannot be derived
and the answer is true, same as outside the admin branch; the gate check stays fail-closed.
Parameters
- $action : string
Return values
boolisCsvExportEnabled()
public
isCsvExportEnabled() : bool
Return values
boolisDeleteAllowed()
Returns whether the user may delete in this list; one answer for the whole grid.
public
isDeleteAllowed() : bool
Used in three places so they cannot contradict each other:
- the row action
deleteis not rendered without the privilege, - the group action
deleteis not offered without it, - HandleTrait::requireOfferedDeletion() returns 403 without it, which covers deleting a single row too, not only bulk.
Replaces a manual condition on the key :Admin:<Module>:<Presenter>:del around action
registration, which most presenters lacked and so offered deleting to anyone.
IMPORTANT: it cannot be decided at registration (addRowAction()): the grid is not yet
attached to the presenter (Nette attaches it after createComponent*() returns) and
getPresenter() would throw. It is asked at render time and in the gate.
IMPORTANT: fail-open outside the admin branch: the derived key would not exist there and would lock deleting for everyone. The gate is the real protection; this is only one of its three checks.
Return values
boolisDragDropEnabled()
public
isDragDropEnabled() : bool
Return values
boolisDragFlat()
Flat drag mode (reordering only, no parent change); see {@see enableDragDrop()}.
public
isDragFlat() : bool
Return values
boolisDragView()
Returns whether the tree drag & drop view is active: a nested `<ul>/<li>` list with SortableJS Nested Sortables. It requires a tree ({@see canReorder()}) and the user having switched on "Reorder" (persistent `reorder`).
public
isDragView() : bool
Return values
boolisPickerMode()
public
isPickerMode() : bool
Return values
boolisPickerSelectable()
Whether the row can be picked in picker mode (false when excluded, e.g. self-reference or descendant).
public
isPickerSelectable(object $entity) : bool
Parameters
- $entity : object
Return values
boolisTreeCollapsible()
Tells whether the tree can be collapsed.
public
isTreeCollapsible() : bool
A non-collapsible grid (menu) behaves as collapsible once it outgrows the limit, otherwise it
would silently render thousands of rows. Without a right bound (rgt) "has children" cannot
be told without loading the children, so the whole tree is always shown.
Return values
boolisTreePathVisible()
Tells whether the flat list shows the "Path" column and the "Show in tree" action: only a tree grid with a right bound (ancestors are found from `lft/rgt`) outside the tree view, where indentation and breadcrumbs carry the path.
public
isTreePathVisible() : bool
Return values
boolisTreeViewChosen()
Tells whether the tree view is chosen: the `view` URL parameter (stored in the session), otherwise the session, otherwise the grid default. The picker modal (parent selection) and a tree without a right bound ("has children" cannot be told, so always whole) always use the tree.
public
isTreeViewChosen() : bool
Return values
boolloadState()
Validates the persistent parameters from the URL.
public
loadState(array<string, mixed> $params) : void
Parameters
- $params : array<string, mixed>
onCreate()
public
onCreate() : void
prepareCell()
Prepares a cell: the column value plus renderer variables for the template `Templates/Default/Cells/<template>.latte`. `link` is the href the template wraps the cell content in ({@see BaseColumn::setLink()}), or null.
public
prepareCell(BaseColumn $column, object $entity) : array{template: string, vars: array, link: ?string, linkTarget: ?string}
Parameters
- $column : BaseColumn
- $entity : object
Return values
array{template: string, vars: arrayrender()
public
render() : void
setAddLink()
"Add" button above the table; not shown unless set.
public
setAddLink(string $destination[, array<string, mixed> $params = [] ][, string|null $privilege = null ]) : self
IMPORTANT: the button is hidden also for users without the privilege to create. The key is
derived from the presenter and the target action (:Admin:<Module>:<Presenter>:add) the same
way as PrivilegeCheckTrait::checkCurrentPrivilege(),
so grids need no manual conditions. It is derived only for a relative action ('add'); an
absolute destination (':Admin:Other:Module:add') points to a foreign screen where the derived
key would not fit and would hide the button wrongly, so nothing is hidden there.
Parameters
- $destination : string
- $params : array<string, mixed> = []
- $privilege : string|null = null
-
custom key instead of the derived one;
''turns the derivation off (for grids that create something other than the presenter name says)
Return values
selfsetAppContext()
public
setAppContext(AppContext $appContext) : $this
Parameters
- $appContext : AppContext
Return values
$thissetComponentParameter()
Sets a component parameter.
public
setComponentParameter(string $name, mixed $value) : void
Parameters
- $name : string
- $value : mixed
setCurrencyContext()
public
setCurrencyContext(CurrencyContext|null $currencyContext) : $this
Parameters
- $currencyContext : CurrencyContext|null
Return values
$thissetDataSource()
Manager the grid reads data from (`findAll()`) and saves changes to.
public
setDataSource(Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>> $dataSource) : self
Parameters
- $dataSource : Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>>
Return values
selfsetDefaultOrder()
Default list order. The first call drops the built-in `id DESC`, further calls add another level (`setDefaultOrder('type')->setDefaultOrder('name')`).
public
setDefaultOrder(string $property[, string $direction = 'asc' ]) : self
IMPORTANT: without dropping it id DESC would stay first and sorting by any other column
would have no visible effect; the setting would silently do nothing.
Parameters
- $property : string
- $direction : string = 'asc'
Return values
selfsetDeleteMethod()
Switches the delete signal and group action to another manager method; see {@see $deleteMethod}.
public
setDeleteMethod(string $method) : self
Opt-in: without the call 'delete' (hard delete) stays and no other grid changes. Shop grids
call setDeleteMethod('softDelete').
Parameters
- $method : string
Return values
selfsetIncludes()
public
setIncludes(array<string|int, string> $includes) : self
Parameters
- $includes : array<string|int, string>
-
relations for findAll (['translations', 'user.role'])
Return values
selfsetItemIdentifier()
Property with the record primary key (default `id`).
public
setItemIdentifier(string $itemIdentifier) : self
Parameters
- $itemIdentifier : string
Return values
selfsetItemsPerPage()
Default rows per page; the user can override it with the 25/50/100 links.
public
setItemsPerPage(int $itemsPerPage) : self
Parameters
- $itemsPerPage : int
Return values
selfsetLanguageContext()
public
setLanguageContext(LanguageContext|null $languageContext) : $this
Parameters
- $languageContext : LanguageContext|null
Return values
$thissetLocalizationContext()
public
setLocalizationContext(LocalizationContext|null $localizationContext) : $this
Parameters
- $localizationContext : LocalizationContext|null
Return values
$thissetPickerData()
Further data carried by the "Select" button (`data-pick-data` JSON); JS spreads it into the opener's fields by the picker `fieldMap`. Fills several fields at once (not only the label), e.g. a user's e-mail and company.
public
setPickerData(array<string, string> $properties) : self
Parameters
- $properties : array<string, string>
-
data key => entity property path
Return values
selfsetPickerExcludeId()
Id of the record that cannot be picked in picker mode (self-reference); its row gets no "Select" button. 0 / null means no exclusion.
public
setPickerExcludeId(int|null $id) : self
Parameters
- $id : int|null
Return values
selfsetPickerExcludeSubtree()
lft/rgt range of the subtree that cannot be picked in picker mode. Excludes the root and all descendants (a node cannot be moved under its descendant). The entity must support `getLft()` (duck typing).
public
setPickerExcludeSubtree(int|null $lft, int|null $rgt) : self
Parameters
- $lft : int|null
- $rgt : int|null
Return values
selfsetPickerLabelCallback()
Label for "Select" computed from the whole entity; use it when one property is not enough (empty for some records, or several fields must be combined). Takes precedence over {@see setPickerLabelProperty()}.
public
setPickerLabelCallback(callable(object): string $callback) : self
IMPORTANT: the label must match labelResolver / the autocomplete of the corresponding
PickerConfig, otherwise the user sees a different text in the modal than after the
selection in the input. Share one formatting function (like PaymentPickerLabel).
Parameters
- $callback : callable(object): string
Return values
selfsetPickerLabelProperty()
Property for the "Select" button label (what is returned to the opener); defaults to the first non-id column.
public
setPickerLabelProperty(string $property) : self
Parameters
- $property : string
Return values
selfsetPickerMode()
Picker mode: the grid serves as a record picker for a foreign form (a modal opened by {@see \App\UI\Admin\System\Components\PickerComponent\Picker}). Hides add, row checkboxes, edit/delete actions and group actions, and gives each row a "Select" action ({@see Templates/Default/Parts/_body.latte}). Filtering, sorting and paging stay; inside the modal they run via AJAX (`picker.js` swaps the dialog body) and the persistent parameter `picker` stays in links because the grid links to `this`.
public
setPickerMode(string $pickerName) : self
The presenter turns it on in createComponent…Grid() by the persistent parameter picker
(BasePresenter::$picker).
Parameters
- $pickerName : string
-
name of the opener's target field (returned on selection)
Return values
selfsetRowDecorator()
Decorator called once after the current page is loaded (see {@see $rowDecorator}).
public
setRowDecorator(callable(array<int, object> $items): void $decorator) : self
Parameters
- $decorator : callable(array<int, object> $items): void
Return values
selfsetSettingContext()
public
setSettingContext(SettingContext $settingContext) : $this
Parameters
- $settingContext : SettingContext
Return values
$thissetThemeContext()
public
setThemeContext(ThemeContext|null $themeContext) : $this
Parameters
- $themeContext : ThemeContext|null
Return values
$thissetTreeChildrenLimit()
Cap of children of one parent (default {@see TREE_CHILDREN_LIMIT}). Above it the first N children and a row "… N more — use search" are rendered; in "Reorder" a node cannot be dropped at the end of the truncated list (the server would reject the position as TREE_STALE).
public
setTreeChildrenLimit(int $limit) : self
Parameters
- $limit : int
Return values
selfsetTreeCollapsible()
Collapsible tree (default `true`): ▸/▾ at the indented column, focus on a subtree, "Expand/Collapse all", expansion state in the session. Data is loaded per parent.
public
setTreeCollapsible([bool $collapsible = true ]) : self
false means an always fully expanded tree without toggles, focus and session, for small
trees dragged across the whole tree (menu). The data path, move contract and lock stay the
same. Safeguard: a tree that grows past TREE_FULL_LIMIT nodes behaves as collapsible
and logs a warning.
Parameters
- $collapsible : bool = true
Return values
selfsetTreeDefaultView()
Default view of a tree grid ({@see self::VIEW_LIST} / {@see self::VIEW_TREE}) until the user switches; the choice is then kept in the session.
public
setTreeDefaultView(string $view) : self
Parameters
- $view : string
Return values
selfsetTreeMoveFactories()
Component factories of the modal, injected by {@see \App\UI\Admin\System\Components\DataGridComponent\DataGridFactory}.
public
setTreeMoveFactories(PickerFactory $pickerFactory, TreePositionFactory $treePositionFactory) : self
Parameters
- $pickerFactory : PickerFactory
- $treePositionFactory : TreePositionFactory
Return values
selfsetTreeScope()
Tree scope filter for several trees in one table (e.g. menuItem.menuId). It is added to the list filters (only that tree) and to the move SQL queries (the lft/rgt recalculation does not touch other trees). Empty means a single tree (pages).
public
setTreeScope(array<string, scalar|null> $scope) : self
Parameters
- $scope : array<string, scalar|null>
-
property => value
Return values
selfsetTreeStructure()
Records form a tree (page, menuItem, category…): the list is ordered depth-first by the order property, indented by level, and rows get arrows to move among siblings.
public
setTreeStructure([string $parentProperty = 'parentId' ][, string $orderProperty = 'lft' ][, string|null $rightProperty = 'rgt' ]) : self
Moving and deleting are done by the model layer
(TreeTrait): a set-based nested-set swap in
the database (lft + rgt, whole subtrees) plus Redis invalidation; deleting removes the whole
subtree and closes the gap. The grid only calls manager->moveUp/moveDown/deleteNode with
buildTreeConfig().
Parameters
- $parentProperty : string = 'parentId'
-
property with the parent id
- $orderProperty : string = 'lft'
-
order property among siblings (lft)
- $rightProperty : string|null = 'rgt'
-
right nested-set bound (rgt), null for none
Return values
selfsetup()
public
setup(BasePresenter|BasePresenter $presenter) : void
Parameters
- $presenter : BasePresenter|BasePresenter
setupAppContext()
public
setupAppContext(AppContext $appContext) : void
Parameters
- $appContext : AppContext
sortIdsByLabel()
Returns ids sorted by label using `Collator` (`strnatcasecmp` without intl). Equal labels keep their original order (stable sort), so sorting again changes nothing.
public
static sortIdsByLabel(array<int, string> $labels[, string $locale = 'cs_CZ' ]) : array<int, int>
Parameters
- $labels : array<int, string>
-
id => label in the current order
- $locale : string = 'cs_CZ'
Return values
array<int, int>typedComponent()
Returns a subcomponent with a verified type.
public
typedComponent(string $name, T> $type) : T
Use it instead of an inline @var above $this['x'] (which does not narrow the type) and
instead of the generic IComponent that $this['x'] returns. See
Form::typedComponent().
Parameters
- $name : string
- $type : T>
Tags
Return values
TcreateComponentGridForm()
protected
createComponentGridForm() : Form
Return values
FormcreateComponentMoveForm()
protected
createComponentMoveForm() : Form
Return values
FormcreateComponentMoveParentPicker()
Parent in the modal: a suggest field with the path plus a modal with the same grid in picker mode (without the node and its subtree).
protected
createComponentMoveParentPicker() : Picker
Return values
PickercreateComponentMovePosition()
protected
createComponentMovePosition() : TreePosition
Return values
TreePositionfrontPresenter()
Returns the front presenter the component is attached to (null outside the front end or when detached).
protected
frontPresenter() : BasePresenter|null
Return values
BasePresenter|nullgetLangId()
protected
getLangId() : int|null
Return values
int|nullgetTranslator()
protected
getTranslator() : ITranslator
Return values
ITranslatorsetTemplateFile()
protected
setTemplateFile(string $dir, string $filename) : void
Parameters
- $dir : string
- $filename : string
setTranslator()
protected
setTranslator(ITranslator $translator) : self
Parameters
- $translator : ITranslator
Return values
selfaddFilterControls()
private
addFilterControls(Form $form, string $name, ColumnFilter $filter) : void
Parameters
- $form : Form
- $name : string
- $filter : ColumnFilter
addMoveNotice()
private
addMoveNotice(string $key, string $type) : void
Parameters
- $key : string
- $type : string
buildMoveTargetParams()
Builds the redirect parameters after success so that the moved node is highlighted and visible.
private
buildMoveTargetParams(int $id, int|null $newParentId) : array<string, mixed>
In a tree the path to the new parent is expanded; when it lies outside the focused subtree, the new parent is focused. A flat list (search) stays as it is.
Parameters
- $id : int
- $newParentId : int|null
Return values
array<string, mixed>buildNestedLevel()
private
buildNestedLevel(array<string|int, mixed> $level) : array<int, array{item: object, children: array, more: int, meta: array}>
Parameters
- $level : array<string|int, mixed>
-
nodes from TreeRowsBuilder (
id,children,more), recursive
Return values
array<int, array{item: object, children: array, more: int, meta: arraybuildParentFilter()
Builds `parentId IS NULL` (roots) or `= focused node`, plus children of expanded nodes.
private
buildParentFilter(object|null $rootNode, array<int, int> $expandedIds) : Filter
Parameters
- $rootNode : object|null
- $expandedIds : array<int, int>
Return values
FilterbuildStateFilters()
Converts search field values into Core filters via the column filter definitions.
private
buildStateFilters() : array<string|int, Filter>
Return values
array<string|int, Filter>buildSubtreeFilters()
Returns filters of the focused node subtree (descendants have `lft` inside its bounds); empty without focus.
private
buildSubtreeFilters(object|null $rootNode) : array<string|int, Filter>
Parameters
- $rootNode : object|null
Return values
array<string|int, Filter>buildTreeConfig()
`TreeConfig` for the model layer (moves), from the tree configuration and scope.
private
buildTreeConfig() : TreeConfig
Return values
TreeConfigbuildTreeCrumbs()
Returns the breadcrumbs of the focused node: ancestors from the bounds (`lft < x and rgt > x`, one query).
private
buildTreeCrumbs(object $rootNode) : array<int, array{id: int|null, label: string}>
Parameters
- $rootNode : object
Return values
array<int, array{id: int|null, label: string}> —from the root down to the parent (the node itself excluded)
callDeleteMethod()
Calls the delete method of the manager configured via {@see setDeleteMethod()} (default `'delete'`); the only place that knows its name, shared by the `delete!` signal ({@see HandleTrait::handleDelete()}) and the group action 'delete' ({@see FormTrait::processGroupAction()}).
private
callDeleteMethod(Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>> $manager, int|array<int, int> $id) : Result
Parameters
- $manager : Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>>
- $id : int|array<int, int>
Return values
ResultconfirmDelete()
Server-side half of the delete confirmation: a delete runs only with the confirmation flag ({@see DataGrid::CONFIRM_FIELD}) in the POST.
private
confirmDelete(string|null $message, array<int, int> $ids[, string|null $actionLabel = null ]) : bool
The modal (datagrid.js) sets the flag after "Delete". Before the bundle initialized (a large
page still loading), without JavaScript, or from a hand-built request, the button submitted the
delete with no question at all (admin walkthrough A18). Without the flag nothing is deleted; the
grid renders a confirmation page instead ("Do you really want to delete these records?"), which
repeats the same request with the flag. An AJAX request gets a warning and a redirect (the modal
never sends one unconfirmed).
Parameters
- $message : string|null
- $ids : array<int, int>
- $actionLabel : string|null = null
-
label of a non-delete bulk action that asks first (null = delete)
Return values
bool —true = confirmed, run it; false = the confirmation page renders instead
countTreeNodes()
Returns the number of tree nodes within the scope (one count query, cached per request).
private
countTreeNodes() : int
Return values
intcreateMultiplierComponent()
Creates a multiplier for the component.
private
createMultiplierComponent(string $name) : Multiplier<string|int, IComponent>
Parameters
- $name : string
Return values
Multiplier<string|int, IComponent>createNewComponentInstance()
Creates a new component instance without adding it to the presenter; used by the multiplier.
private
createNewComponentInstance(string $baseName[, int|string|null $uniqueKey = null ]) : IComponent|null
Parameters
- $baseName : string
- $uniqueKey : int|string|null = null
Return values
IComponent|nullcreateStandardComponent()
Creates a standard component (not a multiplier).
private
createStandardComponent(string $name) : IComponent|null
Parameters
- $name : string
Return values
IComponent|nulldecorateItems()
Calls {@see DataGrid::setRowDecorator()} on the current page when it is set.
private
decorateItems() : void
deleteFlashType()
Returns the flash color for {@see deleteResultKey()}; an explained success with a caveat carries the level of its code.
private
deleteFlashType(Result $result) : string
Parameters
- $result : Result
Return values
stringdeleteResultKey()
Returns the flash key for a delete result.
private
deleteResultKey(Result $result) : string
A permission denial and a database failure get different messages, so the admin can tell whether to fix permissions or report an error. The bridge preserves the result code.
Parameters
- $result : Result
Return values
stringdeleteTreeNodes()
Deletes nodes of a tree grid in bulk; each node is deleted with its subtree ({@see \App\Core\Traits\Api\Models\Services\TreeTrait::deleteTreeNode()}).
private
deleteTreeNodes(array<string|int, int> $ids) : Result
An id that vanished meanwhile (a descendant of an already deleted node) is skipped.
Parameters
- $ids : array<string|int, int>
Return values
ResultderivedAddPrivilege()
`:Admin:<Module>:<Presenter>:<action>` from the attached presenter; `null` when it cannot be derived.
private
derivedAddPrivilege() : string|null
Return values
string|nullfilterControlNames()
private
filterControlNames() : array<string, string>
Return values
array<string, string> —column => control name
findMoveChildren()
private
findMoveChildren(int|null $parentId) : array<int, array{id: int, label: string}>
Parameters
- $parentId : int|null
Return values
array<int, array{id: int, label: string}> —children of the parent in lft order (grid scope)
findMoveNode()
private
findMoveNode(int $id) : object|null
Parameters
- $id : int
Return values
object|nullfindTreeParentIds()
Returns ids of nodes with children within the filters, or null when more than {@see DataGrid::TREE_FULL_LIMIT} nodes are in range (expanding all would render too much).
private
findTreeParentIds(array<string|int, Filter> $extraFilters) : array<int, int>|null
Parameters
- $extraFilters : array<string|int, Filter>
Return values
array<int, int>|nullfinishTreeSignal()
Finishes a tree signal: AJAX outside picker redraws the body (plus flash); otherwise it redirects, which `picker.js` follows.
private
finishTreeSignal([bool $withFlash = false ]) : void
Parameters
- $withFlash : bool = false
flashTranslated()
Flashes a message by key; the admin layout translates `{_'//' . $flash->message}`, so the full path including the component domain is needed.
private
flashTranslated(string $key, string $type) : void
Parameters
- $key : string
- $type : string
flattenPost()
Flattens POST data into `name => value` pairs for hidden fields (`ids[]` and nested arrays keep their bracket names); the confirmation flag itself is left out.
private
static flattenPost(array<string|int, mixed> $data[, string $prefix = '' ]) : array<int, array{0: string, 1: string}>
Parameters
- $data : array<string|int, mixed>
- $prefix : string = ''
Return values
array<int, array{0: string, 1: string}>getNodeBounds()
private
getNodeBounds(object $node) : array{int, int}
Parameters
- $node : object
Return values
array{int, int} —[lft, rgt]
getPageCount()
private
getPageCount() : int
Return values
intgetPaginationSteps()
Paging steps: the neighborhood of the current page plus evenly spread pages (like {@see \App\UI\Front\System\Components\PaginatorComponent\Paginator}).
private
getPaginationSteps() : array<string|int, int>
Return values
array<string|int, int>getTreeSessionKey()
State key: presenter, component and scope (each menu has its own).
private
getTreeSessionKey() : string
Return values
stringgetTreeSessionSection()
private
getTreeSessionSection() : SessionSection
Return values
SessionSectionhasFilterRow()
private
hasFilterRow() : bool
Return values
boolinitializeData()
private
initializeData() : void
isAddAllowed()
Returns whether the logged-in user may see the "add" button.
private
isAddAllowed() : bool
Returns true (behavior unchanged) when the key is unknown (absolute destination, derivation
turned off, presenter outside the admin branch). Hiding only complements the server gate in
actionAdd(); if the derivation missed, it must not hide the button by mistake because the
presenter holds the real protection.
Return values
boolisExplainedDeleteOutcome()
private
isExplainedDeleteOutcome(ResultCode|null $code) : bool
Parameters
- $code : ResultCode|null
Return values
boolisTreeView()
Tells whether the tree list applies: only in the chosen tree view ({@see TreeStateTrait::isTreeViewChosen()}) and until the user searches or sorts by a column, which breaks the hierarchy and switches the grid to the flat list. The default view is the flat paged list.
private
isTreeView() : bool
Return values
boolloadExpandedIds()
private
loadExpandedIds() : array<int, int>|null
Return values
array<int, int>|null —null when the user has not changed the state yet (the default applies)
loadFlatData()
private
loadFlatData(array<string|int, Filter> $coreFilters) : void
Parameters
- $coreFilters : array<string|int, Filter>
loadTreeData()
Loads the tree list by parents: one query `parentId IN (root or focused node + expanded)` ordered by `lft`, without paging.
private
loadTreeData(array<string|int, Filter> $coreFilters) : void
The default state (the user has not collapsed anything) and a non-collapsible tree (menu) mean "everything expanded". For a tree up to DataGrid::TREE_FULL_LIMIT nodes that equals a query without the parent filter (limited to the subtree under focus), so the whole tree is loaded at once. TreeRowsBuilder handles visibility, arrows and the children cap over the same data.
Parameters
- $coreFilters : array<string|int, Filter>
loadTreePaths()
Loads the ancestors of the flat list page rows in one query within the scope: `lft < max(lft) and rgt > min(rgt) and (lft < l1 and rgt > r1 or ...)`, one pair of bounds per parent ({@see TreePathBuilder::pickQueryBounds()}).
private
loadTreePaths(array<int, object> $items) : void
The envelope alone would return almost the whole tree for scattered search results; the OR conditions return exactly the ancestors. Assigning them to rows by intervals happens in PHP.
Parameters
- $items : array<int, object>
moveDialogErrorKey()
private
moveDialogErrorKey(Result $result) : string
Parameters
- $result : Result
Return values
stringmoveNode()
Moves a node up or down by delegating to the manager model layer ({@see \App\Core\Traits\Shared\Models\Managers\TreeTrait}). The tree configuration (lft/rgt/parent properties and scope) comes from {@see \App\UI\Admin\System\Components\DataGridComponent\DataGrid::buildTreeConfig()}.
private
moveNode(int $id, bool $up) : void
Parameters
- $id : int
- $up : bool
moveResultKey()
Returns the flash key of a move result. A rejected contract (`TREE_STALE`) and a lock (`TREE_LOCKED`) are not plain failures: the user should know to reload or wait a moment.
private
moveResultKey(Result $result) : string
tree-drag.js reads the same texts from grid data attributes (AJAX branch).
Parameters
- $result : Result
Return values
stringprepareTreePathTemplate()
"Path" column and "In tree" action in the flat tree list: the path goes after the indented column (node name), without one after the last column. Row highlighting applies only in the tree.
private
prepareTreePathTemplate(array<string, BaseColumn> $columns) : void
Parameters
- $columns : array<string, BaseColumn>
-
columns that are actually rendered
prepareTreeTemplate()
Tree variables for the template: row metadata, toggles, focus and breadcrumbs, URLs for JS.
private
prepareTreeTemplate(bool $isTreeUi) : void
Parameters
- $isTreeUi : bool
processGroupAction()
Handles a group action submit: passes the checkbox ids to the action callback; `delete` without a callback deletes through the manager.
private
processGroupAction(GroupAction $action, Form $form) : void
Parameters
- $action : GroupAction
- $form : Form
processMoveForm()
private
processMoveForm(ArrayHash $values) : void
Parameters
- $values : ArrayHash
processSearch()
Handles the search submit: stores field values in the persistent state and redirects.
private
processSearch(Form $form) : void
Parameters
- $form : Form
reloadMoveNodeFromForm()
private
reloadMoveNodeFromForm() : void
requireDataSource()
Returns the grid manager; signals and actions run after the presenter configured the grid, so a missing data source is a programmer error.
private
requireDataSource() : Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>>
Return values
Manager<BaseEntity, ServiceInterface<string|int, BaseEntity>>requireDeletePrivilege()
IMPORTANT: server-side gate for bulk delete, key `…:del`.
private
requireDeletePrivilege() : void
Without it a logged-in user without the delete right could delete in bulk, because the
registered action and CSRF protect only against a foreign site. Every screen with bulk
delete must have the key :Admin:<Module>:<Presenter>:del allowed for the admin role,
otherwise this fail-closed gate would lock even the administrator out.
NOTE: outside the admin branch (a grid in another module, a component without a presenter) it is not enforced, as in requireEditPrivilege(); the derived key would not exist there and would lock the action for everyone.
requireEditPrivilege()
IMPORTANT: server-side gate for writes in the grid: inline editing, relation toggles and tree moves.
private
requireEditPrivilege() : void
These signals changed data without asking for any right, so anyone inside the admin could
flip any switch in any grid by a hand-built URL. The input validations (column exists, is
inline editable, value is in options) check the shape of the input, not permission.
The key is derived from the attached presenter as :Admin:<Module>:<Presenter>:edit, by the
same rule as PrivilegeCheckTrait::checkCurrentPrivilege()
and the add button in DataGrid::setAddLink().
Inline editing is editing, so edit fits, and no per-grid registration is needed. Every
screen with inline, relation or tree writes must have the edit key allowed for admin.
NOTE: when the key cannot be derived (a grid outside an admin presenter) the gate lets the
call through. Failing closed would break a foreign context that does not follow the admin
naming convention; the real gate remains checkAdminAccess() in startup(), which everyone
has to pass.
requireGroupActionPrivilege()
Gate for any group action; the action declares its own privilege ({@see GroupAction::setPrivilege()}), `delete` has it built in.
private
requireGroupActionPrivilege(GroupAction $action) : void
NOTE: it mirrors the condition the button is rendered by; whoever sees the action must pass, and vice versa.
Parameters
- $action : GroupAction
requireOfferedDeletion()
IMPORTANT: server-side delete gate; responds 403 when the grid does not offer deletion in this request.
private
requireOfferedDeletion() : void
Presenters add the delete action conditionally:
if ($this->isAllowed(':Admin:System:UserGroup:del')) {
$grid->addRowAction(RowAction::create('delete')->setSignal('delete'));
}
A hidden button is no protection: without this gate the delete! signal could be called by
a hand-built URL even without the right. The gate has no key of its own; it mirrors the
condition the UI already uses (the component is rebuilt in the signal request too), so it
cannot lock out anyone who sees the button. The presenter condition is therefore
authoritative: to tighten a grid, wrap addRowAction() and addGroupAction() in isAllowed().
NOTE: per-row visibility (RowAction::setVisibleWhen()) is not handled here; it mirrors
entity state (e.g. a closed work sheet) and the model guards it in beforeDelete().
requireTreeMoveAllowed()
private
requireTreeMoveAllowed() : void
resolveCollatorLocale()
Returns the collation locale by the admin language (`cs` to `cs_CZ`), Czech by default.
private
resolveCollatorLocale() : string
Return values
stringresolveExpandedIds()
Returns the expanded nodes: the session, otherwise the default state (a small tree means all nodes with children).
private
resolveExpandedIds() : array<int, int>
Return values
array<int, int>resolveMoveNode()
Returns the node being moved: from the form value (submit) or from the signal parameter (open).
private
resolveMoveNode() : object|null
Return values
object|nullresolveMoveParentLabel()
private
resolveMoveParentLabel(int $id) : string|null
Parameters
- $id : int
Return values
string|nullresolveOrderBys()
Returns the ordering for `findAll()`; user ordering takes precedence over the default.
private
resolveOrderBys() : array<string, bool>
Return values
array<string, bool> —property path => true (asc) / false (desc)
resolveRowLabel()
Shared core of {@see getPickerLabel()} and {@see getRowLabel()}: the first meaningful text of the row.
private
resolveRowLabel(object $entity) : string
Parameters
- $entity : object
Return values
stringresolveTreeLabelProperty()
Returns the property of the indented column (node name), which the parent suggest searches by.
private
resolveTreeLabelProperty() : string|null
Return values
string|nullresolveTreeParentId()
private
resolveTreeParentId(object $entity) : int|null
Parameters
- $entity : object
Return values
int|nullresolveTreeRootNode()
Returns the focused node (`treeRoot`) as an entity, or null for the whole tree.
private
resolveTreeRootNode() : object|null
A missing or foreign node resets the parameter and raises a notice flag. A 404 would break
the picker modal (picker.js inserts the response into the dialog) and a shared link to a
deleted node; the right reaction is to show the whole tree and say why.
Return values
object|nullrowDeleteConfirmText()
Confirmation text of the row delete action (the same the modal shows).
private
rowDeleteConfirmText() : string|null
Return values
string|nullshowMoveModal()
Fills and opens the shared modal with the current form state (idempotent).
private
showMoveModal() : void
slugifyColumnName()
private
slugifyColumnName(string $column) : string
Parameters
- $column : string
Return values
stringstateToString()
Converts a persistent state value (mixed, from the URL) to a string for form defaults.
private
stateToString(mixed $value) : string
Parameters
- $value : mixed
Return values
stringstoreExpandedIds()
private
storeExpandedIds(array<int, int> $ids) : void
Parameters
- $ids : array<int, int>
stringify()
private
stringify(mixed $value) : string
Parameters
- $value : mixed
Return values
stringsuggestMoveParents()
Suggests parents: LIKE over the name column property, without the node and its subtree, with the path in the label so that equal names can be told apart.
private
suggestMoveParents(string $query, int|null $nodeId, int|null $lft, int|null $rgt) : array<int, array{id: int, label: string}>
Parameters
- $query : string
- $nodeId : int|null
- $lft : int|null
- $rgt : int|null
Return values
array<int, array{id: int, label: string}>t()
Translates a key in the component domain.
private
t(string $key) : string
Parameters
- $key : string
Return values
stringupdateResultKey()
Returns the flash key for an inline update result; an explained refusal carries the message of its code (absolute key into the `results` domain).
private
updateResultKey(Result $result) : string
Parameters
- $result : Result