Set trigger targets arbitrary levels above current form context (#3465)
Fixes #3260. Enables setting the target field for the trigger API to a form context an arbitrary number of levels above the current field by prepending the field name with `^` for each level to go up. For instance, if you had a field [allow_pictures] in the base form and a [records] repeater with [image] fields, and you set the target field for the trigger on [image] to [^allow_pictures] then it would work properly instead of looking for an [allow_pictures] field on the [records] field. Credit to @MartynasJanu. Documented in edc78b584b
This commit is contained in:
parent
4a2e959fb8
commit
13dadaa667
|
|
@ -18,6 +18,11 @@ class FormField
|
|||
*/
|
||||
const NO_SAVE_DATA = -1;
|
||||
|
||||
/**
|
||||
* @var string A special character in yaml config files to indicate a field higher in hierarchy
|
||||
*/
|
||||
const HIERARCHY_UP = '^';
|
||||
|
||||
/**
|
||||
* @var string Form field name.
|
||||
*/
|
||||
|
|
@ -461,6 +466,12 @@ class FormField
|
|||
$triggerField = array_get($this->trigger, 'field');
|
||||
$triggerCondition = array_get($this->trigger, 'condition');
|
||||
|
||||
// Check for parent field reference for the trigger condition
|
||||
$triggerFieldParentLevel = $this->getNumberOfPrecedingSymbols($triggerField, self::HIERARCHY_UP);
|
||||
if ($triggerFieldParentLevel > 0) {
|
||||
$triggerField = substr($triggerField, $triggerFieldParentLevel);
|
||||
}
|
||||
|
||||
// Apply these to container
|
||||
if (in_array($triggerAction, ['hide', 'show']) && $position != 'container') {
|
||||
return $attributes;
|
||||
|
|
@ -471,7 +482,11 @@ class FormField
|
|||
return $attributes;
|
||||
}
|
||||
|
||||
if ($this->arrayName) {
|
||||
// Reduce the field reference for the trigger condition field
|
||||
if ($this->arrayName && $triggerFieldParentLevel > 0) {
|
||||
$parentFormName = $this->reduceFieldNameHierarchy($this->arrayName, $triggerFieldParentLevel);
|
||||
$fullTriggerField = $parentFormName.'['.implode('][', HtmlHelper::nameToArray($triggerField)).']';
|
||||
} elseif ($this->arrayName) {
|
||||
$fullTriggerField = $this->arrayName.'['.implode('][', HtmlHelper::nameToArray($triggerField)).']';
|
||||
}
|
||||
else {
|
||||
|
|
@ -489,6 +504,40 @@ class FormField
|
|||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the field name hierarchy depth by $level levels.
|
||||
* country[city][0][street][0] turns into country[city][0] when reduced by 1 level;
|
||||
* country[city][0][street][0] turns into country when reduced by 2 levels;
|
||||
* etc.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param int $level
|
||||
* @return string
|
||||
*/
|
||||
protected function reduceFieldNameHierarchy($fieldName, $level) {
|
||||
$parentFormName = HtmlHelper::nameToArray($fieldName);
|
||||
$sliceLength = count($parentFormName) - $level * 2;
|
||||
if ($sliceLength <= 1) {
|
||||
return $parentFormName[0];
|
||||
}
|
||||
|
||||
$parentFormName = array_slice($parentFormName, 0, $sliceLength);
|
||||
$parentFormNameFirst = array_shift($parentFormName);
|
||||
return $parentFormNameFirst.'['.implode('][', $parentFormName).']';
|
||||
}
|
||||
|
||||
/**
|
||||
* If $string begins with any number of consecutive symbols,
|
||||
* returns the number, otherwise returns 0
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $symbol
|
||||
* @return int
|
||||
*/
|
||||
protected function getNumberOfPrecedingSymbols($string, $symbol) {
|
||||
return strlen($string) - strlen(ltrim($string, $symbol));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds attributes used specifically by the Input Preset API
|
||||
* @param array $attributes
|
||||
|
|
|
|||
Loading…
Reference in New Issue