5

In my custom module I have two custom option in the system configuration. Values of the second option depend on the value of the first option. My problem is that inside the source model of the second option I don't know how to retrieve the value of the first option.

Options

Here's how the options are defined:

View in Magento admin panel

\app\code\Company\Images\etc\adminhtml\system.xml:

<field id="custom_folder" translate="label" sortOrder="10" type="text" showInDefault="1" showInWebsite="1" showInStore="1">
    <label>Custom folder</label>
</field>
<field id="list_of_icons" translate="label" sortOrder="20" type="select" showInDefault="1" showInWebsite="1" showInStore="1">
    <label>List of icons</label>
    <source_model>Company\Images\Model\System\Config\Source\Icons\Custom</source_model>
</field>

And here's a short description of what these options actually do:

  • first option: custom_folder - folder path, user can define a path to custom folder which stores images (icons)

  • second option: list_of_icons - dropdown list of all icons inside the folder which is defined in the first option.

From this list the user can select an icon which will be displayed on the frontend. This dropdown list will be used in multiple places in the system configuration pages of my module (to add icons to multiple elements of the frontend) but it will always show the list of icons from the folder selected in the custom_folder option.

Source model

For the second option list_of_icons I've created a source model. It should list all icons which exist in the folder specified by user in the first option (custom_folder). Here's the code of the source model:

\app\code\Company\Images\Model\System\Config\Source\Icons\Custom.php:

<?php
namespace Company\Images\Model\System\Config\Source\Icons;

class Custom
{
    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $_storeManager;

    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $_scopeConfigInterface;

    public function __construct(
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\App\Config\ScopeConfigInterface $configScopeConfigInterface

    ) {
        $this->_storeManager = $storeManager;
        $this->_scopeConfigInterface = $configScopeConfigInterface;
    }

    public function toOptionArray()
    {
        // Get current store view ID
        $storeId = $this->_storeManager->getStore()->getId();

        // Get value of the first option in the current store view
        $folderPath = $this->_scopeConfigInterface->getValue(
            'images/icons/custom_folder',
            'store',
            $storeId
        );

        $options = [];
        // Here we need to list all image files from the specified folder.
        // It's not relevant to my question, so this part of code can be omitted.
        // ...

        return $options;
    }
}

What I tried to do

So inside that source model in the toOptionArray() method I need to retrieve the value of the first option (the folder path). Of course I need the value from the current store view:

enter image description here

I tried to do it like this:

// Get current store view ID
$storeId = $this->_storeManager->getStore()->getId();

// Get value of the first option in the current store view
$folderPath = $this->_scopeConfigInterface->getValue(
    'images/icons/custom_folder',
    'store',
    $storeId
);

but this line:

$storeId = $this->_storeManager->getStore()->getId();

always returns the ID of the Default Config, instead of the current store view ID.

So my code always retrieves the value of the option from the Default Config, no matter in which store view I am at the moment on the system configuration page in admin panel.

I need the value from the current store view, because each store view can have different folder path configured by user, so in each store view the list of icons (presented in the second option) can be completely different.

The problem

So, to sum up, the problem is the following:

  • How to correctly retrieve the value of the first option when I'm inside the source model of the second option?

And this problem comes down to:

  • How I can get the ID of the current store view inside the code of the source model?

If I have the ID of the current store view I will be able to easily retrieve the value of the first option.

  • did you tried to get storeview id from url param? I think it adds store view id in url param while switching storeview – Piyush Feb 2 '18 at 12:30
6
+75

The way you approach to make the custom configuration fields dependant will be achieved through the steps suggested by @Piyush and @Lez(Using source models with request library).

However, this approach has a drawback - which forces the merchant to save, once the first configuration field value is entered. Only then, you can use that value for the second field, which results in bad user(merchant) experience. Definitely, not a recommended one.

An alternative approach will be using javascript with ajax loader - the way Magento fetches the regions for the respective countries. Debugging that further, end me up in the

vendor/magento/module-config/view/adminhtml/templates/system/config/js.phtml

This template file is loaded in the configuration pages and the script in the template is responsible for fetching the regions for the respective country when modified. Line no: 125

reloadRegionField : function(event)
    {
        this.reload = true;
        var countryElement = Event.element(event);
        if (countryElement && countryElement.id) {
            var regionElement  = $(countryElement.id.replace(/country_id/, 'region_id'));
            if (regionElement) {
                this.regionElement = regionElement;
                if (countryElement.value.length) {
                    var url = this.regionsUrl+'parent/'+countryElement.value;
                    this.loader.load(url, {}, this.refreshRegionField.bind(this));
                } else {
                    this.clearRegionField(this.regionElement.disabled);
                }
            }
        }
    }

If you have a look at this method, it uses the country value and fetches the respective regions using the loader. This method gets binded to the country field(refer bindCountryRegionRelation() in the same class).

So you can override the same template, add your own class with respective methods(event handler) to reload the second field. Finally, bind that event handler to the first field.

Summing up, it is good to follow the same approach to fetch the image files(using loader) when "custom_folder" input value gets changed. Also, this will fetch only the current store value.

I hope this heads you in the right direction.

0

As Piyush stated in his comment, you can get the current storeview ID from the request when switching store views.

You can do it like this in your icons model:

protected $request;

public function __construct(
    \Magento\Framework\App\RequestInterface $request
) {
    $this->request = $request;
}

And then in the toOptionArray function get the current store id like this:

$storeId = (int) $request->getParam('store');

$folderPath = $this->_scopeConfigInterface->getValue(
    'images/icons/custom_folder',
    'store',
    $storeId
);

Seems like you got the rest covered. Good luck!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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