I need to add a image field in my dynamic rows system config
1 Answer 1
Here I made an image uploader in a dynamic array https://github.com/mavlikhanov/image_dymanic_config/
In short, add in system.xml backend_model field:
 <section id="swatch" translate="label" type="text" sortOrder="300" showInDefault="1" showInWebsite="1" showInStore="1">
 <class>separator-top</class>
 <label>Image Array Swatch</label>
 <tab>mr</tab>
 <resource>Mr_ImageDynamicConfig::config</resource>
 <group id="image_serializer" translate="label" type="text" sortOrder="140" showInDefault="1" showInWebsite="1" showInStore="1">
 <field id="image" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="0">
 <label>Image</label>
 <frontend_model>Mr\ImageDynamicConfig\Block\Adminhtml\System\Config\ImageFields</frontend_model>
 <backend_model>Mr\ImageDynamicConfig\Model\Config\Backend\Serialized\ArraySerialized</backend_model>
 <upload_dir>var/uploads/swatch/image_serializer</upload_dir>
 </field>
 </group>
 </section>
Next step, create Mr\ImageDynamicConfig\Model\Config\Backend\Serialized\ArraySerialized class
public function __construct(
 \Magento\Framework\Model\Context $context,
 \Magento\Framework\Registry $registry,
 \Magento\Framework\App\Config\ScopeConfigInterface $config,
 \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
 \Mr\ImageDynamicConfig\Model\Config\ImageConfig $imageConfig,
 \Mr\ImageDynamicConfig\Model\ImageUploaderFactory $imageUploaderFactory,
 \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
 \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
 array $data = [],
 Json $serializer = null
) {
 $this->imageUploaderFactory = $imageUploaderFactory;
 $this->imageConfig = $imageConfig;
 parent::__construct(
 $context,
 $registry,
 $config,
 $cacheTypeList,
 $resource,
 $resourceCollection,
 $data,
 $serializer
 );
}
public function beforeSave(): ArraySerialized
{
 $value = $this->getValue();
 $value = $this->mapRows($value);
 $this->setValue($value);
 return parent::beforeSave();
}
private function mapRows(array $rows): array
{
 $iconUploader = $this->imageUploaderFactory->create([
 'path' => $this->getPath(),
 'uploadDir' => $this->getUploadDir(),
 ]);
 $uploadedFiles = $iconUploader->upload();
 $swatches = $this->imageConfig->getSwatches();
 foreach ($rows as $id => $data) {
 if (isset($uploadedFiles[$id])) {
 $rows[$id][ImageFields::IMAGE_FIELD] = $uploadedFiles[$id];
 continue;
 }
 if (!isset($swatches[$id])) {
 unset($swatches[$id]);
 } else {
 $rows[$id] = $this->matchRow($data, $swatches[$id]);
 }
 }
 return $rows;
}
private function matchRow(array $row, array $configTabIcon): array
{
 foreach ($row as $fieldName => $value) {
 if (is_array($value) && $fieldName == ImageFields::IMAGE_FIELD) {
 $row[ImageFields::IMAGE_FIELD] = $configTabIcon[ImageFields::IMAGE_FIELD];
 }
 }
 return $row;
}
private function getUploadDir(): string
{
 $fieldConfig = $this->getFieldConfig();
 if (!array_key_exists('upload_dir', $fieldConfig)) {
 throw new \Magento\Framework\Exception\LocalizedException(
 __('The base directory to upload file is not specified.')
 );
 }
 if (is_array($fieldConfig['upload_dir'])) {
 $uploadDir = $fieldConfig['upload_dir']['value'];
 if (array_key_exists('scope_info', $fieldConfig['upload_dir'])
 && $fieldConfig['upload_dir']['scope_info']
 ) {
 $uploadDir = $this->_appendScopeInfo($uploadDir);
 }
 if (array_key_exists('config', $fieldConfig['upload_dir'])) {
 $uploadDir = $this->getUploadDirPath($uploadDir);
 }
 } else {
 $uploadDir = (string)$fieldConfig['upload_dir'];
 }
 return $uploadDir;
}
Method 'mapRows' upload image and merge data with config rows
Displaying image: 1) in frontend_model add Mr\ImageDynamicConfig\Block\Adminhtml\System\Config\ImageFields
 const IMAGE_FIELD = 'image';
const NAME_FIELD = 'name';
private $imageRenderer;
protected function _prepareToRender()
{
 $this->addColumn(
 self::IMAGE_FIELD,
 [
 'label' => __('Image'),
 'renderer' => $this->getImageRenderer()
 ]
 );
 $this->addColumn(
 self::NAME_FIELD,
 [
 'label' => __('Name'),
 ]
 );
 $this->_addAfter = false;
 $this->_addButtonLabel = __('Add');
}
private function getImageRenderer()
{
 if (!$this->imageRenderer) {
 $this->imageRenderer = $this->getLayout()->createBlock(
 \Mr\ImageDynamicConfig\Block\Adminhtml\Form\Field\ImageColumn::class,
 '',
 ['data' => ['is_render_to_js_template' => true]]
 );
 }
 return $this->imageRenderer;
}
2)\Mr\ImageDynamicConfig\Block\Adminhtml\Form\Field\ImageColumn
public function setInputName(string $value)
{
 return $this->setName($value);
}
public function setInputId(string $value)
{
 return $this->setId($value);
}
protected function _toHtml(): string
{
 $imageButton = $this->getLayout()
 ->createBlock(ImageButton::class)
 ->setData('id', $this->getId())
 ->setData('name', $this->getName());
 return $imageButton->toHtml();
}
Method _toHtml render block \Mr\ImageDynamicConfig\Block\Adminhtml\ImageButton and return html with file upload button and uploaded image
P.S. this is my first answer don’t judge strictly, please
- 
 The solution is not functioning properly in the admin panel. We are unable to see the tab, and there is no error log available for this issue.Praveen Chelumalla– Praveen Chelumalla2023年06月18日 07:30:03 +00:00Commented Jun 18, 2023 at 7:30