I have a fieldset in the admin panel with one parent select (has 5 options) and 2 fields, which should be displayed in case the parent value select will be 3, 4 or 5. I have not found the examples of similar logic in magento and tried to write by analogy with the usual dependence, but it doesn’t work. In my example, the dependent fields are displayed only while choosing the options with the value 5 form the select and are not displayed when choosing 1, 2, 3, or 4.
Full code (block example):
<?php
namespace Siarhey\Test\Block\Adminhtml\Promo\Quote\Edit\Tab;
class Actions extends \Magento\Backend\Block\Widget\Form\Generic implements
\Magento\Backend\Block\Widget\Tab\TabInterface
{
/**
* @param \Magento\Backend\Block\Template\Context $context
* @param \Magento\Framework\Registry $registry
* @param \Magento\Framework\Data\FormFactory $formFactory
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Data\FormFactory $formFactory,
array $data = []
) {
parent::__construct($context, $registry, $formFactory, $data);
}
public function getTabLabel()
{
return __('Actions');
}
public function getTabTitle()
{
return __('Actions');
}
public function canShowTab()
{
return true;
}
public function isHidden()
{
return false;
}
protected function _prepareForm()
{
$model = $this->_coreRegistry->registry('current_promo_quote_rule');
/** @var \Magento\Framework\Data\Form $form */
$form = $this->_formFactory->create();
$form->setHtmlIdPrefix('rule_');
$fieldset = $form->addFieldset(
'action_fieldset',
['legend' => __('Rules')]
);
$parentField = $fieldset->addField(
'simple_action',
'select',
[
'label' => __('Apply'),
'name' => 'simple_action',
'options' => [
1 => __('Amount 1'),
2 => __('Discount 1'),
3 => __('Amount 2'),
4 => __('Discount 2'),
]
]
);
$childFieldOne = $fieldset->addField(
'amount',
'text',
[
'name' => 'amount',
'required' => true,
'class' => 'validate-not-negative-number',
'label' => __('Amount')
]
);
$model->setAmount($model->getAmount() * 1);
$childFieldTwo = $fieldset->addField(
'percent',
'text',
['name' => 'percent', 'label' => __('Percent')]
);
$model->setPercent($model->getPercent() * 1);
$this->setChild(
'form_after',
$this->getLayout()->createBlock(
'Magento\Backend\Block\Widget\Form\Element\Dependence'
)->addFieldMap(
$parentField->getHtmlId(),
$parentField->getName()
)->addFieldMap(
$childFieldOne->getHtmlId(),
$childFieldOne->getName()
)->addFieldMap(
$childFieldTwo->getHtmlId(),
$childFieldTwo->getName()
)->addFieldDependence(
$childFieldOne->getName(),
$parentField->getName(),
'1,3'
)->addFieldDependence(
$childFieldTwo->getName(),
$parentField->getName(),
'2,4'
)
);
$form->setValues($model->getData());
if ($model->isReadonly()) {
foreach ($fieldset->getElements() as $element) {
$element->setReadonly(true, true);
}
}
$this->setForm($form);
return parent::_prepareForm();
}
}
Result (view):
Code sample 1 (doesn’t work):
/*
* $parentField is select with values (0,1,2,3,4,5)
*/
$this->setChild(
'form_after',
$this->getLayout()->createBlock(
'Magento\Backend\Block\Widget\Form\Element\Dependence'
)->addFieldMap(
$parentField->getHtmlId(),
$parentField->getName()
)->addFieldMap(
$childFieldOne->getHtmlId(),
$childFieldOne->getName()
)->addFieldDependence(
$childFieldOne->getName(),
$parentField->getName(),
'3'
)->addFieldDependence(
$childFieldOne->getName(),
$parentField->getName(),
'4'
)->addFieldDependence(
$childFieldOne->getName(),
$parentField->getName(),
'5'
)->addFieldMap(
$parentField->getHtmlId(),
$parentField->getName()
)->addFieldMap(
$childFieldTwo->getHtmlId(),
$childFieldTwo->getName()
)->addFieldDependence(
$childFieldTwo->getName(),
$parentField->getName(),
'3'
)->addFieldDependence(
$childFieldTwo->getName(),
$parentField->getName(),
'4'
)->addFieldDependence(
$childFieldTwo->getName(),
$parentField->getName(),
'5'
)
);
Code sample 2 (doesn’t work):
/*
* $parentField is select with values (0,1,2,3,4,5)
*/
$this->setChild(
'form_after',
$this->getLayout()->createBlock(
'Magento\Backend\Block\Widget\Form\Element\Dependence'
)->addFieldMap(
$parentField->getHtmlId(),
$parentField->getName()
)->addFieldMap(
$childFieldOne->getHtmlId(),
$childFieldOne->getName()
)->addFieldMap(
$parentField->getHtmlId(),
$parentField->getName()
)->addFieldMap(
$childFieldTwo->getHtmlId(),
$childFieldTwo->getName()
)->addFieldDependence(
$childFieldOne->getName(),
$parentField->getName(),
array('3', '4', '5')
)->addFieldDependence(
$childFieldTwo->getName(),
$parentField->getName(),
array('3', '4', '5')
)
);
Result:
Notice: Array to string conversion in
/var/www/magento2/app/code/Magento/Backend/Block/Widget/Form/Element/Dependence.php
on line 95
UPDATE:
Code sample 3 (doesn't work, if selected value is not '3,4,5'
):
// Parent field
$typeField = $fieldset->addField(
'action_type',
'select',
[
'label' => __('Type'),
'name' => 'action_type',
'options' => ['1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '3,4,5' => '3,4,5']
]
);
$this->setChild(
'form_after',
$this->getLayout()->createBlock(
'Magento\Backend\Block\Widget\Form\Element\Dependence'
)->addFieldMap(
$parentField->getHtmlId(),
$parentField->getName()
)->addFieldMap(
$childFieldOne->getHtmlId(),
$childFieldOne->getName()
)->addFieldMap(
$typeField->getHtmlId(),
$typeField->getName()
)->addFieldMap(
$childFieldTwo->getHtmlId(),
$childFieldTwo->getName()
)->addFieldDependence(
$childFieldOne->getName(),
$parentField->getName(),
'3,4,5'
)->addFieldDependence(
$childFieldTwo->getName(),
$parentField->getName(),
'3,4,5'
)
);
Has someone faced the same issue and found a solution?
Update:
Maybe someone else can the check the presence of this issue? I’ve checked it on 3 different installations and this solution ( the line with the values coma separated ) still doesn’t work.
Best Answer
If you check the code that is responsible for adding the corresponding fields in accordance with the dependencies in the file
lib/web/mage/adminhtml/form.js
, you will see the following scheme there:In case you set comma separated values, for example:
then while debuging you will see that
indexOf
is trying to find the existing value in the one-element array that is, in your case, a your comma-separated value. This element can't be found:A step-by-step output of
console.log
from the method:To create fields multi dependency, you can use the same coma-separated value, but with some modifications. You will just need the block, that will extend
\Magento\Backend\Block\Widget\Form\Element\Dependence
:As you can see, the value is FORCED to be changed into a 1-value array.
The main problem lies in the
addFieldDependence
of the class\Magento\Backend\Block\Widget\Form\Element\Dependence
:The point is that the value (the line from the dependency), is transferred as the only element of the array.
indexOf
tries to find the value of the corresponding chosen option, but fails to locate the exact match. As a result, it returns 'false'.There's also no way to transfer the values as an array, as PHP returns the
Notice: Array to string conversion
because of the converting of'value' => (string)$refField
.In our example, we have recreated the one-element array into a multi-element one, where each element consists of several dependencies.
The code of your dependence should be modified (you'll need to change the block). This is how to:
The result should look like this:
UPD
If you are sure that you will be using a comma separated value in the future, the best way will be to adding the const
UNIQUE_DELIMITER
with the required value of the delimiter to the classVendor\Module\Block\Widget\Form\Element\Dependence
: E.g.Next, modify the partition method:
Then, use
Vendor\Module\Block\Widget\Form\Element\Dependence::UNIQUE_DELIMITER
in your classActions
.For your convenience, add the class
Dependence
(after namespace):And write the code this way: