Picker
extends BaseComponent
in package
uses
PrivilegeGuardTrait
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
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
$container
public
Container
$container
Attributes
- #[Inject]
$routerDispatcher
public
RouterDispatcher
$routerDispatcher
$translator
public
ITranslator
$translator
Tags
$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.picker'
$config
private
PickerConfig
$config
$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>
__construct()
public
__construct() : mixed
createComponent()
public
createComponent(string $name) : IComponent|null
Parameters
- $name : string
Return values
IComponent|nullgetAppContext()
public
getAppContext() : AppContext
Return values
AppContextgetComponentParameter()
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|nullgetLanguageContext()
public
getLanguageContext() : LanguageContext|null
Return values
LanguageContext|nullgetLocalizationContext()
public
getLocalizationContext() : LocalizationContext|null
Return values
LocalizationContext|nullgetRouterDispatcher()
public
getRouterDispatcher() : RouterDispatcher
Return values
RouterDispatchergetSettingContext()
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|nullhandleCreate()
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
Return values
boolinitializeAllContexts()
public
initializeAllContexts() : void
injectDeviceDetector()
public
injectDeviceDetector(DeviceDetector $detector) : void
Parameters
- $detector : DeviceDetector
onCreate()
public
onCreate() : void
render()
public
render() : void
setAppContext()
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
setConfig()
public
setConfig(PickerConfig $config) : self
Parameters
- $config : PickerConfig
Return values
selfsetCurrencyContext()
public
setCurrencyContext(CurrencyContext|null $currencyContext) : $this
Parameters
- $currencyContext : CurrencyContext|null
Return values
$thissetLanguageContext()
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
$thissetRowIndex()
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
selfsetRowIndices()
Sets the row indices for (possibly nested) multipliers, outside in.
public
setRowIndices(array<int, string> $indices) : self
Parameters
- $indices : array<int, string>
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
$thissetup()
public
setup(BasePresenter|BasePresenter $presenter) : void
Parameters
- $presenter : BasePresenter|BasePresenter
setupAppContext()
public
setupAppContext(AppContext $appContext) : void
Parameters
- $appContext : AppContext
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
TfrontPresenter()
Returns the front presenter the component is attached to (null outside the front end or when detached).
protected
frontPresenter() : BasePresenter|null
Return values
BasePresenter|nullgetTranslator()
protected
getTranslator() : ITranslator
Return values
ITranslatorisTargetAllowed()
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
boolrequirePrivilege()
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
-
AdminPageentity (hydrated, hence justobject)
Return values
string|nullsetTemplateFile()
protected
setTemplateFile(string $dir, string $filename) : void
Parameters
- $dir : string
- $filename : string
setTranslator()
protected
setTranslator(ITranslator $translator) : self
Parameters
- $translator : ITranslator
Return values
selfcontainerPath()
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|nullcreateStandardComponent()
Creates a standard component (not a multiplier).
private
createStandardComponent(string $name) : IComponent|null
Parameters
- $name : string
Return values
IComponent|nullfindControl()
private
findControl(Container $parent, string $name) : BaseControl|null
Parameters
- $parent : Container
- $name : string
Return values
BaseControl|nullrequirePresenter()
private
requirePresenter() : Presenter
Return values
PresenterresolveControls()
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|nullresolveParent()
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