Dynamic Store Configuration Fields
Dynamic Store Configuration Fields

Dynamic Store Configuration Fields

Published April 3, 2017 in Development
How to change Magento 2 Increment ID for orders, invoices, credit memos and shipments
How to Change Magento 2 Increment ID for Orders, Invoices, Credit Memos and Shipments
February 7, 2017
Creating a Custom Widget in Magento 2
Creating a Custom Widget in Magento 2
April 28, 2017

Magento’s store configuration functionality allows developers to quickly and efficiently define config fields for their modules. This efficiency promotes flexible and configurable modules, saving developers and merchants time and money.

In some cases, however, a fixed list of defined config fields isn’t sufficient to configure a more dynamic feature. Fortunately, it’s relatively straightforward to implement dynamically generated store config fields, allowing developers to support complicated flexibility.

Example Use Case

The requirement for this example is that, for countries which are configured to require a state/region, only certain regions are allowed.

These countries are configured in store config at General -> General -> State Options -> State is Required for. In order to configure which regions are allowed for each country, new store config fields will need to be added, one for each configured country. Since the configured countries could change at any time, it will not be possible to hard code the allowed regions fields in system.xml. Instead, a field will need to be dynamically added to the State Options group for each configured country.

Dynamic Fields

Approach

Each element in the store config hierarchy (tab, section, and group) extends \Magento\Config\Model\Config\Structure\Element\AbstractComposite. When setting its data, AbstractComposite specifically looks for an array at key children, and uses this value to populate the children elements.

This provides the opportunity to craft a plugin to add (or remove) children, which will eventually be used to populate the store config UI. The parent element of fields is a config group, so \Magento\Config\Model\Config\Structure\Element\Group is the specific class where calls to setData() should be intercepted.

Now that an interception point has been established, all that’s needed is to add values to the $data['children'] array.

The format for the values of this array mostly follow the format of fields in system.xml, with a few additions. Below is an example with common values set on the field.

In this example, a field needs to be dynamically added for every selected country in the General -> General -> State Options -> State is Required for field. Using \Magento\Directory\Helper\Data to retrieve which countries are selected and their known regions (if any), the plugin shell can generate these dynamic fields.

In the event that a country has a known list of regions, a multiselect field is used. Otherwise, a textarea field is generated to allow free-form region entry.

Results

After fully implementing the plugin, dynamically created country-specific config fields are appended to the State Options group.

In the following screenshot, the default countries are selected, along with Afghanistan, for good measure. (Click for full page screenshot.)

Abbreviated Dynamic Fields Admin UI

Of course, adding dynamic fields is useless if they don’t store the field values. This is handled seamlessly by Magento, and the dynamic fields’ values are stored in core_config_data with the computed path.

core_config_data dynamic fields screenshot

These values can be retrieved by their computed paths in the same way as any other store config value.

Dynamic Groups

For some applications with multiple sets of fields, it may make more sense to create entire groups of fields dynamically. This can be done in a similar way, one level higher in the store config hierarchy.

Approach

Just as dynamic fields are added by a plugin around the group model’s setData() method, dynamic groups are added by a plugin around the setData() method of the section model, \Magento\Config\Model\Config\Structure\Element\Section. This plugin is nearly identical, but the expected format of arrays appended to $data['children'] is one level higher.

In this example, it’s possible to add an entire config group for each country selected by using this format. This is easily implemented using a plugin similar to the dynamic fields plugin.

Results

Similar to dynamic fields, after this plugin is implemented a dynamic group is shown in the General -> General tab, one for each selected country. (Click for full page screenshot.)

Screenshot of Dynamic Groups in Admin UI

Additionally, values of fields in dynamic groups are correctly saved to core_config_data.

core_config_data dynamic groups screenshot

Where to Go From Here

Retrieving Values

Retrieving values of dynamic fields or fields of dynamic groups is the same as getting any other store config field, except that the path is computed. Below is an example of a config helper to look up the values from this example.

Dynamic Sections and Tabs

Similar to fields and groups, it’s possible to create an around plugin on the setData() method of \Magento\Config\Model\Config\Structure\Element\Tab and add children one level higher than a group. These dynamic sections will show in the admin as expected. However, clicking on them redirects back to one of the hard-coded sections. Since each section has its own URL, there are probably additional routing concerns for dynamic sections.

Example Module

A complete module demonstrating these code examples is available here: https://github.com/ericthehacker/example-dynamicconfigfields. Use it wisely.

Be aware of the following module notes.

  • The module implements example dynamic fields and groups, as well as methods to retrieve their values. Actually using values to restrict available regions (as expressed in the example use case), however, is left as an exercise for the reader.
  • There is duplicated code between the dynamic fields and groups plugins. This is intentional to ensure that each example plugin is easy to read.

5 Comments

  1. Syed Muneeb Ul Hasan says:

    That’s a detailed and great tutorial!

  2. RandomDude says:

    Thank you! It was very helpful.

  3. faran says:

    how to add image field field then, im facing problem in generating image fields. i have my own backend_model class, i did add my backend_model in the array but the field on admin frontend doesn’t seems to upload the file. (in simple words the image fields don’t get the backend_model class).
    Thanks for this great tutorial by the way.

  4. Faran says:

    Thanks very informative tutorial, but i ran into a problem with image type fields, the fields do generate dynamically but i cant upload the image. It looks like the field is not getting my “back_end model” class. So thats why i cant upload the image. when select the image and save config, the image name just shows with the field.
    Please help me, how can i solve this problem!

  5. Konzhi says:

    Hey! Thanks for this piece of knowledge, it really fast-tracked me to achieving desired results. However this exact solution is not working, as when saving configuration, class \Magento\Config\Model\Config is unable to find groups and fields in configuration data that is requested directly from backend and has no information about our custom fields. Best workaround I’ve found is to have a Plugin that observes \Magento\Config\Model\Config\Structure\Data merge() method and add you custom data there. This way custom groups and fields will be present in both cases: when rendering fields in Admin and when saving them as well.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.