Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magento 2 : How to add dynamic url for Ajax call from UiComponent?

I am making a form using UiComponent. In options.js, I would like to make an ajax call. However It's getting 404 not found error. I would like to know how we can get the right url.

In the form:

<field name="attribute_id">
    <argument name="data" xsi:type="array">
        <item name="options" xsi:type="object">Vendor\Module\Model\Source\Myvalues</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="component" xsi:type="string">Vendor_Module/js/form/element/options</item>
            <item name="formElement" xsi:type="string">select</item>
            <item name="sortOrder" xsi:type="number">210</item>
        </item>
    </argument>
</field>

In options.js

define([
    'jquery',
    'underscore',
    'uiRegistry',
    'Magento_Ui/js/form/element/select',
    'Magento_Ui/js/modal/modal',
    'mage/url'
], function ($, _, uiRegistry, select, modal, url) {
    'use strict';

    return select.extend({

        /**
         * On value change handler.
         *
         * @param {String} value
         */
        onUpdate: function (value) {
            console.log('Selected Value: ' + value);

            var field1 = uiRegistry.get('index = field1');

  var field2 = uiRegistry.get('index = field2');
  field2.hide();
  var field3Depend1 = uiRegistry.get('index = field3Depend1');


console.log(field2.visibleValue);
 var linkUrl = url.build('customajax');
  console.log('linkurl='+linkUrl);

 //var name = document.getElementsByName("product[name]")[0].value;
   // var type = document.getElementsByName("product[product_category_type]")[0].value;

    $.ajax({
        url: 'BASEURL????'+linkUrl,
        showLoader: true,
        data: {form_key: window.FORM_KEY, 'value':value},
        type: "POST",
          dataType : 'json',
        success: function(result){

            alert(result);
        }
    });


         return this._super();
        },
    });
});

It gives 404 not found error. I would like to make an ajax call.

like image 673
Aqsa Fatima Avatar asked Oct 26 '25 18:10

Aqsa Fatima


2 Answers

I have tried various method to bring a url dynamically into a UI component, but the standard and safe way I think is to add via meta data of the UI xml component itself.

To inject the dynamic data (not needed if you just want to added a static URL) in the component use the following code:

Form DataProvider.php:

<?php

namespace Vendor\Module\Ui\DataProvider\Profile;

use Magento\Framework\UrlInterface;

class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
    public $collection;

    /**
     * @var $addFieldStrategies
     */
    public $addFieldStrategies;

    /**
     * @var $addFilterStrategies
     */
    public $addFilterStrategies;

    /** @var UrlInterface  */
    public $url;

    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        UrlInterface $url,
        \Vendor\Module\Model\ResourceModel\MyModel\CollectionFactory $collectionFactory,
        $addFieldStrategies = [],
        $addFilterStrategies = [],
        $meta = [],
        $data = []
    ) {
        parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
        $this->url = $url;
        $this->collection = $collectionFactory->create();
        $this->addFieldStrategies = $addFieldStrategies;
        $this->addFilterStrategies = $addFilterStrategies;
    }

    /**
     * @return array
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function getMeta()
    {
        $meta = parent::getMeta();
        // general -> fieldset name
        // attribute_id -> field name
        $meta["general"]['children']["attribute_id"]['arguments']['data']['config']['url'] =
            $this->url->getUrl('myfrontname/mycontroller/myaction', ['_nosid' => true]);

        return $meta;
    }

    /**
     *
     * @return array
     */
    public function getData()
    {
        if (!$this->getCollection()->isLoaded()) {
            $this->getCollection()->load();
        }

        /** @var array $items */
        $items = $this->getCollection();
        $data = [];

        foreach ($items as &$item) {
            $item->setData("id_field_name", 'id');
            $data[$item->getId()] = $item->getData();
        }
        return $data;
    }
}

Here, function getMeta() is injecting the URL value.

UI Component xml field:

<field name="attribute_id">
    <argument name="data" xsi:type="array">
        <item name="options" xsi:type="object">Vendor\Module\Model\Source\Myvalues</item>
        <item name="config" xsi:type="array">
            <item name="url" xsi:type="string" />
            <item name="url" xsi:type="url" path="mymodule/mycontroller/myaction">
                        <param name="_nosid">1</param>
                    </item>
            <item name="dataType" xsi:type="string">text</item>
            <item name="label" translate="true" xsi:type="string">Attribute</item>
            <item name="component" xsi:type="string">Vendor_Module/js/form/element/options</item>
            <item name="formElement" xsi:type="string">select</item>
            <item name="sortOrder" xsi:type="number">210</item>
        </item>
    </argument>
</field>

Here, I have added <item name="url" xsi:type="url" path="mymodule/mycontroller/myaction"> <param name="_nosid">1</param> </item> the url key will have the dynamic URL and will be available on JS UI component.

Now in options.js, use the url field as below:

define([
    'jquery',
    'underscore',
    'uiRegistry',
    'Magento_Ui/js/form/element/select',
    'Magento_Ui/js/modal/modal',
    'mage/url'
], function ($, _, uiRegistry, select, modal, url) {
    'use strict';

    return select.extend({

        /**
         * On value change handler.
         *
         * @param {String} value
         */
        onUpdate: function (value) {
            // As `this` context will not be available inside ajax,
            // so either use local variable `self` or prepare the URL outside the `$.ajax`  
            var self = this;

            console.log('Selected Value: ' + value);

            var field1 = uiRegistry.get('index = field1');

            var field2 = uiRegistry.get('index = field2');
            field2.hide();
            var field3Depend1 = uiRegistry.get('index = field3Depend1');
            var linkUrl = url.build('customajax');

            $.ajax({
                url: self.url + linkUrl,
                showLoader: true,
                data: {form_key: window.FORM_KEY, 'value':value},
                type: "POST",
                dataType : 'json',
                success: function(result) {
                    alert(result);
            }
         });


         return this._super();
        },
    });
});

Edit: I have updated the answer with the below answer.

like image 193
Milind Singh Avatar answered Oct 29 '25 09:10

Milind Singh


It can also be added via url xml datatype (Only static urls can be added. No need to modify meta in this case.).

UI Component xml field:

<dataSource name="your_module_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">Your\Module\Data\Provider</argument>
            <argument name="name" xsi:type="string">your_module_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">id</argument>
            <argument name="requestFieldName" xsi:type="string">id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="submit_url" xsi:type="url" path="*/*/save"/>
                    <item name="validate_url" xsi:type="url" path="*/*/validate"/>
                    <item name="get_custom_url" xsi:type="url" path="your/custom/url"/>
                </item>
            </argument>
        </argument>
        <argument name="data" xsi:type="array">
            <item name="js_config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
            </item>
        </argument>
    </dataSource>

Here, I have added get_custom_url of type url which will have the URL and will be available on JS.

Now in options.js, use the url field as below:

define([
    'jquery',
    'underscore',
    'uiRegistry',
    'Magento_Ui/js/form/element/select',
    'Magento_Ui/js/modal/modal',
    'mage/url'
], function ($, _, uiRegistry, select, modal, url) {
    'use strict';

    return select.extend({

        /**
         * On value change handler.
         *
         * @param {String} value
         */
        onUpdate: function (value) {
            console.log('Selected Value: ' + value);

            var field1 = uiRegistry.get('index = field1');

            var field2 = uiRegistry.get('index = field2');
            field2.hide();
            var field3Depend1 = uiRegistry.get('index = field3Depend1');
            var linkUrl = url.build('customajax');

            var source = uiRegistry.get(this.provider);
            var ajaxUrl = source.get_custom_url;
            $.ajax({
                url: ajaxUrl + linkUrl,
                showLoader: true,
                data: {form_key: window.FORM_KEY, 'value':value},
                type: "POST",
                dataType : 'json',
                success: function(result) {
                    alert(result);
            }
         });


         return this._super();
        },
    });
});
like image 34
Eayshwary Srivastava Avatar answered Oct 29 '25 09:10

Eayshwary Srivastava