0

I have a form for adding animals with a field called species. This UI Component is:

<field formElement="select" name="species" sortOrder="10">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="source" xsi:type="string">Animal</item>
        </item>
    </argument>
    <settings>
        <dataType>text</dataType>
        <label translate="true">Species</label>
        <dataScope>species</dataScope>
        <validation>
            <rule name="required-entry" xsi:type="boolean">false</rule>
        </validation>
    </settings>
    <formElements>
        <select>
            <settings>
                <options class="Vendor\Module\Model\Config\Source\Species"/>
            </settings>
        </select>
    </formElements>
</field>

Vendor\Module\Model\Config\Source\Species returns an array of animals (e.g. cat, dog, cow, horse).

The issue is that, the client has asked that if the customer has more than 1 animal to show then an extra species field should come for each animal. The developer at the time has coded this on the front end to save the multiple species as a json.

But it gets worse, they've also coded the json to have a second question - 'amount' as well, which shows how many of each animal the customer has.

An example of the json is:

[{"species":"Horse","amount":"4"},{"species":"Cat","amount":"2"}]

How do I modify my UI Component form (Vendor\Module\view\adminhtml\ui_component\animal_form.xml) to show a drop-down when the value is from the source array ('cat', 'dog', etc), and multiple fields (perhaps in a table?) of species and amounts if the response is in json?

2
0

My suggestion is to take a look at the screen at Marketing/Cart Price Rules

enter image description here

Particularly, the section Manage Coupon Codes in this screen.

I would create a form to add an animal for your customer entry. This form would be a lot simpler that the form I show above and the generate button would become a button you may label 'register a new animal'

Then, finally, when the button register would be hit, the table used for coupon code would also need to be replicated. And this table would display the list of animals.

To render a table is not to complex. Here your challenge will be that your grid will need to read its data from various sources and potential will need to parse some json. Likely you will need to create a DataProvider and the latter will have the ability to parse the data and assign it to the ui component to render the grid data.

I appreciate this is vague answer at this stage. However, it is a big amount of work too and hopefully this solution may give you at least some sort of directions.

Good luck

0

I have written another solution and it seems more hopeful to work for you.

My solution consists in enabling the customer entity in Magento to be assigned some animals data. The data can be either some array ['dog', 'cat'] or just like you [{"species":"Horse","amount":"4"},{"species":"Cat","amount":"2"}]

then, I have added a tab section in my screen and within this tab, I have a table

enter image description here

Of course, what we want to describe is how to parse the data and finally how to enable the data to be maintained within this table.

first to my screen, I have added the section that will contain the table:

<fieldset name="assign_animals" sortOrder="40">
        <settings>
            <collapsible>true</collapsible>
            <label translate="true">Animals with Customer</label>
        </settings>
        <container name="assign_animals_container" sortOrder="160">
            <htmlContent name="html_content">
                <block name="gallery" class="Mbs\BackendScreen\Block\Adminhtml\CustomerAnimal\AssignAnimals"/>
            </htmlContent>
        </container>
    </fieldset>

then I have create the AssignAnimals block and that is this block that will centralise all the data interaction and parsing.

Just to give you the important mechanisms, this function retrieves all the possible animals in the system and assign the quantity info if the customer happens to own one of the animals.

/**
     * @return string
     */
    public function getAnimalsJson()
    {
        return $this->customerAnimalReader->getAllAnimalsInJson($this->getCustomer());
    }

then, finally, the javascript is what will update the post fields and will enable the data to be present in the controller so that the customer entity can be updated

/* global $, $H */

define([
    'mage/adminhtml/grid'
], function () {
    'use strict';

    return function (config) {
        var animalsInfo = config.animalsInfo,
            gridJsObject = window[config.gridJsObjectName],
            tabIndex = 1000;

        $('in_customer_animals').value = Object.toJSON(animalsInfo);

        /**
         * Register Category Product
         *
         * @param {Object} grid
         * @param {Object} element
         * @param {Boolean} checked
         */
        function registerCustomerAnimal(grid, element, checked) {
            $('in_customer_animals').value = Object.toJSON(animalsInfo);
        }

        /**
         * Change product amount
         *
         * @param {String} event
         */
        function amountChange(event) {
            var element = Event.element(event);

            if (element) {
                for (var i = 0; i < animalsInfo.length; i++) {
                    if (animalsInfo[i].species === element.animalObject.species) {
                        animalsInfo[i].amount = element.value;
                        break;
                    }
                }
                $('in_customer_animals').value = Object.toJSON(animalsInfo);
            }
        }

        /**
         * Initialize category product row
         *
         * @param {Object} grid
         * @param {String} row
         * @param {String} key
         */
        function customerAnimalRowInit(grid, row, key) {
            var amount = $(row).getElementsByClassName('input-text')[0];

            if (amount) {
                amount.animalObject = animalsInfo[key];
                amount.tabIndex = tabIndex++;
                Event.observe(amount, 'keyup', amountChange);
            }
        }

        gridJsObject.initRowCallback = customerAnimalRowInit;
        gridJsObject.checkboxCheckCallback = registerCustomerAnimal;

        if (gridJsObject.rows) {
            gridJsObject.rows.each(function (row, key) {
                customerAnimalRowInit(gridJsObject, row, key);
            });
        }
    };
});

I post a screenshot showing how the controller receives the table post data when the table data have changed. enter image description here

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.