CoolCMS API

Picker extends BaseComponent
in package
uses PrivilegeGuardTrait

FinalYes

Selects a related object into a form; replaces a long `<select>`.

Renders a text input with a suggester and a button that opens a modal with the show grid of the target entity in picker mode (the row has "Select" instead of edit/delete). JS writes the selected id into the form's hidden field (a real Nette control, so validation, setDefaults and onSuccess work natively) by its htmlId, and the label into the text input.

Generic and loaded as a multicontrol through Multiplier (createComponentPicker), so one page can hold several pickers, even two for the same entity (two different fields). Configuration (data and field binding) is in PickerConfig; it is built by the presenter's picker trait (UserPickerTrait, PagePickerTrait, ...) in pickers(), which is pure and callable also for the AJAX signal suggest!.

Tags
see
DataGrid::setPickerMode()

Table of Contents

Properties

$container  : Container
$routerDispatcher  : RouterDispatcher
$translator  : ITranslator
$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
$config  : PickerConfig
$rowIndices  : array<int, string>
Row indices of the container path, outside in (`addresses[2]` -> `['2']`; nested `parameterGroups[1].parameters[0]` -> `['1','0']`). Empty means a top-level field.

Methods

__call()  : mixed
Dispatches `renderXyz()` to `render('Xyz', ...$args)`.
__construct()  : mixed
createComponent()  : IComponent|null
getAppContext()  : AppContext
getComponentParameter()  : mixed
Returns a component parameter, or null when it is not set.
getContainer()  : Container
getCurrencyContext()  : CurrencyContext|null
getLanguageContext()  : LanguageContext|null
getLocalizationContext()  : LocalizationContext|null
getRouterDispatcher()  : RouterDispatcher
getSettingContext()  : SettingContext
getSettings()  : array<int, array<string, mixed>>
getThemeContext()  : ThemeContext|null
handleCreate()  : void
Creates a new record straight from the suggester: the user types a text that is not in the code list, clicks "Add ..." and the picker selects the new record at once.
handleSuggest()  : void
Suggester (AJAX): returns JSON with a list of items. Calls the callback from the configuration, so the picker knows neither the manager nor the filters.
hasServiceByType()  : bool
Returns whether the container has a service of the given type.
initializeAllContexts()  : void
injectDeviceDetector()  : void
onCreate()  : void
render()  : void
setAppContext()  : $this
setComponentParameter()  : void
Sets a component parameter.
setConfig()  : self
setCurrencyContext()  : $this
setLanguageContext()  : $this
setLocalizationContext()  : $this
setRowIndex()  : self
Sets the multiplier row index (one level); backward-compatible wrapper over {@see setRowIndices()}.
setRowIndices()  : self
Sets the row indices for (possibly nested) multipliers, outside in.
setSettingContext()  : $this
setThemeContext()  : $this
setup()  : void
setupAppContext()  : void
typedComponent()  : T
Returns a subcomponent with a verified type.
frontPresenter()  : BasePresenter|null
Returns the front presenter the component is attached to (null outside the front end or when detached).
getTranslator()  : ITranslator
isTargetAllowed()  : bool
Returns whether the logged-in user may open the given admin target. For visibility (tiles, autocomplete, buttons); it does not throw.
requirePrivilege()  : void
Throws 403 when the logged-in user lacks the given admin privilege.
resolvePageTarget()  : string|null
Returns the RBAC key of the target page: `<presenter>:<action>`, e.g. `:Admin:System:User:show`.
setTemplateFile()  : void
setTranslator()  : self
containerPath()  : array<int, string>
Returns the container path, outside in (`['parameterGroups','parameters']`); empty means top-level.
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).
findControl()  : BaseControl|null
requirePresenter()  : Presenter
resolveControls()  : BaseControl}
Finds the form controls the picker belongs to: the hidden one with the id (required) and an optional text display control. Works for a top-level field and for a field inside a multiplier row (`$form[targetContainer][rowIndex][targetField]`).
resolveFieldMap()  : array<string, string>
Finds the htmlId of the target control for each mapped field ({@see PickerConfig::getFieldMap()}); JS then fills these fields too after selecting.
resolveForm()  : Form|null
Finds the target form ({@see PickerConfig::getFormName()}) by walking the component tree upward from the picker. Works whether the picker is hosted on a presenter (the form is a direct child of the presenter, classic admin forms) or inside a component (the form is a child of the hosting component, e.g. the parameter form engine, where the component creates the form itself).
resolveParent()  : Container|null
Returns the container with the picker fields: the form (top-level), a multiplier row, or a nested multiplier row. Walks the container path outside in and descends into the row by the matching index from {@see $rowIndices} on each level.

Properties

$componentParameters

protected array<string, mixed> $componentParameters = []

component parameters set by setComponentParameter()

$translatorDomain

protected string|null $translatorDomain = 'admin.system.components.picker'

$rowIndices

Row indices of the container path, outside in (`addresses[2]` -> `['2']`; nested `parameterGroups[1].parameters[0]` -> `['1','0']`). Empty means a top-level field.

private array<int, string> $rowIndices = []

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>

createComponent()

public createComponent(string $name) : IComponent|null
Parameters
$name : string
Return values
IComponent|null

getComponentParameter()

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
Container

getSettings()

public getSettings() : array<int, array<string, mixed>>
Return values
array<int, array<string, mixed>>

handleCreate()

Creates a new record straight from the suggester: the user types a text that is not in the code list, clicks "Add ..." and the picker selects the new record at once.

public handleCreate([string $text = '' ]) : void

IMPORTANT: the gate is the first statement. Without it the picker would bypass the privileges of the target presenter: a user without ProductSetLink:add could create links through a foreign form.

The creation itself is done by the closure from the config (it knows the manager, translations and duplicates); the picker only returns {id, label}, which picker.js fills exactly as if the user had selected an existing item. The host form is not submitted, so the user's work in progress stays untouched.

Parameters
$text : string = ''
Attributes
#[Requires]
$methods: 'POST'

handleSuggest()

Suggester (AJAX): returns JSON with a list of items. Calls the callback from the configuration, so the picker knows neither the manager nor the filters.

public handleSuggest([string $q = '' ]) : void

picker.js sends the query as a bare q=... (the generic client does not know the unique id of this instance). Nette routes such an unprefixed parameter to the presenter parameters, not the component's, so the signal argument would stay empty; q is therefore read directly from the presenter in that case. A prefixed ...-q received natively as the signal argument takes precedence for backward compatibility.

Parameters
$q : string = ''

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
phpstan-assert-if-true

class-string $className

Return values
bool

setComponentParameter()

Sets a component parameter.

public setComponentParameter(string $name, mixed $value) : void
Parameters
$name : string
$value : mixed

setRowIndex()

Sets the multiplier row index (one level); backward-compatible wrapper over {@see setRowIndices()}.

public setRowIndex(string|null $index) : self
Parameters
$index : string|null
Return values
self

setRowIndices()

Sets the row indices for (possibly nested) multipliers, outside in.

public setRowIndices(array<int, string> $indices) : self
Parameters
$indices : array<int, string>
Return values
self

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
template
Return values
T

frontPresenter()

Returns the front presenter the component is attached to (null outside the front end or when detached).

protected frontPresenter() : BasePresenter|null
Return values
BasePresenter|null

getTranslator()

protected getTranslator() : ITranslator
Return values
ITranslator

isTargetAllowed()

Returns whether the logged-in user may open the given admin target. For visibility (tiles, autocomplete, buttons); it does not throw.

protected isTargetAllowed(string|null $key) : bool

IMPORTANT: fail-closed like requirePrivilege(): an empty key and a presenter without isAllowed() both mean no. A component that skips this question lists the target to everyone.

Parameters
$key : string|null
Return values
bool

requirePrivilege()

Throws 403 when the logged-in user lacks the given admin privilege.

protected requirePrivilege(string $key) : void

Call it as the first statement of a mutating signal, before loading data, so the check cannot be bypassed by something being written first.

Parameters
$key : string

resolvePageTarget()

Returns the RBAC key of the target page: `<presenter>:<action>`, e.g. `:Admin:System:User:show`.

protected static resolvePageTarget(object|null $page) : string|null

Same interpretation as Menu::filterByPrivileges(), BasePresenter::authorizeListing() and PrivilegeCheckTrait::checkCurrentPrivilege(). The key is derived from the page target only, never from a file or class name.

Returns null when the page is missing or has no presenter, so there is nothing to allow.

Parameters
$page : object|null

AdminPage entity (hydrated, hence just object)

Return values
string|null

setTemplateFile()

protected setTemplateFile(string $dir, string $filename) : void
Parameters
$dir : string
$filename : string

setTranslator()

protected setTranslator(ITranslator $translator) : self
Parameters
$translator : ITranslator
Return values
self

containerPath()

Returns the container path, outside in (`['parameterGroups','parameters']`); empty means top-level.

private containerPath() : array<int, string>
Return values
array<int, string>

createMultiplierComponent()

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|null

createStandardComponent()

Creates a standard component (not a multiplier).

private createStandardComponent(string $name) : IComponent|null
Parameters
$name : string
Return values
IComponent|null

findControl()

private findControl(Container $parent, string $name) : BaseControl|null
Parameters
$parent : Container
$name : string
Return values
BaseControl|null

requirePresenter()

private requirePresenter() : Presenter
Return values
Presenter

resolveControls()

Finds the form controls the picker belongs to: the hidden one with the id (required) and an optional text display control. Works for a top-level field and for a field inside a multiplier row (`$form[targetContainer][rowIndex][targetField]`).

private resolveControls() : BaseControl}
Return values
BaseControl}

resolveFieldMap()

Finds the htmlId of the target control for each mapped field ({@see PickerConfig::getFieldMap()}); JS then fills these fields too after selecting.

private resolveFieldMap() : array<string, string>
Return values
array<string, string> —

data key to field htmlId

resolveForm()

Finds the target form ({@see PickerConfig::getFormName()}) by walking the component tree upward from the picker. Works whether the picker is hosted on a presenter (the form is a direct child of the presenter, classic admin forms) or inside a component (the form is a child of the hosting component, e.g. the parameter form engine, where the component creates the form itself).

private resolveForm() : Form|null

For presenter-hosted pickers the walk up the nearest common ancestor reaches the presenter and finds the form the same way as $presenter->getComponent(name).

Return values
Form|null

resolveParent()

Returns the container with the picker fields: the form (top-level), a multiplier row, or a nested multiplier row. Walks the container path outside in and descends into the row by the matching index from {@see $rowIndices} on each level.

private resolveParent() : Container|null
Return values
Container|null
On this page

Search results