3

Having 2 Drop-downs where the second one should load options according to the first one selections, but both come from the EAV models, I want to make them work in the admin but I can understand how to, I already populated the options from DB, but how to interconnect them is what I can't see

My form.xml file looks like this:

<fieldset name="General">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string"/>
            </item>
        </argument>
        <field name="datafeed_id">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Vendor\Module\Model\Filters\Attribute\Source\Config</item>
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" translate="true" xsi:type="string">DataFeed</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="source" xsi:type="string">Filters</item>
                    <item name="sortOrder" xsi:type="number">10</item>
                    <item name="dataScope" xsi:type="string">datafeed_id</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">false</item>
                    </item>
                </item>
            </argument>
        </field>
        <field name="attr_code">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Vendor\Module\Model\Filters\Attribute\Source\Attributes</item>
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" translate="true" xsi:type="string">Attribute</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="source" xsi:type="string">Filters</item>
                    <item name="sortOrder" xsi:type="number">20</item>
                    <item name="dataScope" xsi:type="string">attr_code</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">false</item>
                    </item>
                </item>
            </argument>
        </field>
        <field name="eval_op">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Vendor\Module\Model\Filters\Attribute\Source\Operators</item>
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" translate="true" xsi:type="string">Operator</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="source" xsi:type="string">Filters</item>
                    <item name="sortOrder" xsi:type="number">30</item>
                    <item name="dataScope" xsi:type="string">eval_op</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">false</item>
                    </item>
                </item>
            </argument>
        </field>
        <field name="eval_val">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Vendor\Module\Model\Filters\Attribute\Source\Conditions</item>
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" translate="true" xsi:type="string">Condition</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="source" xsi:type="string">Filters</item>
                    <item name="sortOrder" xsi:type="number">40</item>
                    <item name="dataScope" xsi:type="string">eval_val</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">false</item>
                    </item>
                </item>
            </argument>
        </field>
        <field name="filter_status">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Vendor\Module\Model\Filters\Attribute\Source\Status</item>
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" translate="true" xsi:type="string">Status</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="source" xsi:type="string">Filters</item>
                    <item name="sortOrder" xsi:type="number">50</item>
                    <item name="dataScope" xsi:type="string">filter_status</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">false</item>
                    </item>
                </item>
            </argument>
        </field>
    </fieldset>
  • Yeah I checked it but that is not working for Data retrieved from DB depending on the first drop-down field the data for the second one should load dynamically – Esteban Flores Sep 25 '17 at 12:04
0

There are several ways how to do this, so below is just one example. For purpose of simplicity lets say that you have one select(A), and based on its value (or change of its value) you want to load new options for the other select (B) (with ajax in this example). The example below was used where select A represented attributes in magento and it was populating select B with their options.

You want to create new component for the select A that looks something like this:

define([
    'jquery',
    'Magento_Ui/js/form/element/select',
    'uiRegistry'
], function ($, Select, uiRegistry) {
    var self;

    return Select.extend({
        initialize: function () {
            self = this;
            this._super();

            self.value.subscribe(function () {
                self.updateValueOptions();
            });

            return this;
        },

        /**
         * Update options in value select.
         */
        updateValueOptions: function () {
            if (self.value()) {
                $.ajax({
                    url: 'http://myajaxcallback.com/',
                    type: 'post',
                    dataType: 'json',
                    cache: false,
                    showLoader: true,
                    data: {attributeId: self.value()}
                }).
                done(function (response) {
                    if (!response.error) {
                        uiRegistry.get('my_form.my_form.fieldsetname.bselectname').
                        options(response.options);
                    }
                });
            }
            else {
                uiRegistry.get('my_form.my_form.fieldsetname.bselectname').options([]);
            }
        }
    });
});

Each time the value of select A changes(attribute in this case), this component will take the value and if it's not empty it will start ajax request to your controller looking for json data.

The controller should look something like this:

    <?php
namespace Company\Values\Controller\Adminhtml\Values;

use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\ResultFactory;

class Load extends \Magento\Backend\App\Action
{

    /** @var \Magento\Eav\Api\AttributeRepositoryInterface */
    private $eavAttributeRepository;

    /** @var \Magento\Eav\Model\ResourceModel\Entity\Attribute */
    private $eavAttributeResource;

    /**
     * Load constructor.
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute $eavAttributeResource
     * @param \Magento\Eav\Api\AttributeRepositoryInterface $eavAttributeRepository
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Eav\Model\ResourceModel\Entity\Attribute $eavAttributeResource,
        \Magento\Eav\Api\AttributeRepositoryInterface $eavAttributeRepository
    ) {
        parent::__construct($context);
        $this->eavAttributeRepository = $eavAttributeRepository;
        $this->eavAttributeResource   = $eavAttributeResource;
    }

    const ADMIN_RESOURCE = 'Company_Module::aclrule';

    /**
     * Dispatch request
     *
     * @return \Magento\Framework\Controller\ResultInterface|ResponseInterface
     * @throws \Magento\Framework\Exception\NotFoundException
     */
    public function execute()
    {
        $result = $this->resultFactory->create(ResultFactory::TYPE_JSON);

        $responseData = [
            'error' => true
        ];

        try {
            $attribute               = $this->eavAttributeRepository->get('catalog_product', $this->_request->getParam('attributeId', null));
            $responseData['error']   = false;
            $responseData['options'] = $attribute->getSource()->getAllOptions();
        } catch (\Exception $e) {
        }

        return $result->setData($responseData);
    }
}

This is by no means perfect and needs a bit work (hardcoded values, perhaps moving the ajax to separate file etc.), but it should give you pretty good overview of such a feature. If you already have the options for select B loaded somewhere, just remove the ajax call and write your logic there.

Documentation is a good read about how two components can communicate with each other.

  • Thanks for the detailed answer I'll take a look to it and if it works will mark it as resolved – Esteban Flores Sep 27 '17 at 14:15

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.