1

I need to add a image field in my dynamic rows system config

enter image description here

1 Answer 1

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

1
  • 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. Commented Jun 18, 2023 at 7:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.