6

Is there a right way pass data (request value) to form ui-component?
reproduce-image I have try to setData from DataProvider define in form-ui.xml but not work. After form load complete this field must be populated data (initial value)

/**
 * Get data from provider and populate
 * @param void
 * @return array
 */
public function getData()
{

    if (isset($this->loadedData)) {
        return $this->loadedData;
    }

    if ($itemId)
        $items = $this->collection->getItems();

    $data = $this->dataPersistor->get('form_item');
    if (!empty($data)) {
       //Do something
    } else {
       //When form init without any data
       // I want to setData for some field here
    }

    return $this->loadedData;
}

My current question:
1 - How to setData in the right way for ui way? If my way not right is there a better way to do setdata for field
2 - Side question: How core-team can make magento find exactly which form to interactive. In old way form , we can define form original with form tag, htmlIdPrefix ... etc But in new form i can't find anywhere in uiform.xml to configuration id form, form prefix .. I am curious how it work
It will be great if know about it

8
+100

In your custom_form.xml file

<field name="your_field_id">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">{Vendorname}\{Modulename}\Model\Classname</item>
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">Name label</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="source" xsi:type="string">[source_here]</item>
                    <item name="dataScope" xsi:type="string">your_field_id</item>
                    <item name="caption" xsi:type="string" translate="true">-- Please Select --</item>
                </item>
            </argument>
        </field>

    In above -- Please Select -- is set as default custom message for dropdown.

Where you can set select dynamic option from this class,

{Vendorname}\{Modulename}\Model\Classname using toOptionArray() method.

In DataProvider.php file,

<?php
namespace Yourmodule\Modulename\Model\Path;

class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{

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



public function getData()
{
    if (isset($this->loadedData)) {
        return $this->loadedData;
    }

    $itemId = $this->_request->getParam('page_id');

    if ( !empty($itemId) ) {
    $items = $this->collection->getItems();
    foreach ($items as $item) {
        $this->loadedData[$item->getId()] = $item->getData();
    }

    $data = $this->dataPersistor->get('form_item');

    if (!empty($data)) {
       //Do something
       $this->loadedData[$item->getId()] = $item->getData();
    } 
    return $this->loadedData;
}

}
  • I have tried this but not work. Seem DataProvider only setdata if entity exist in collection . I can't setdata entity not create . In my case item not exist before you save but i need to setdata for some field as initial value to prepare for form before save. Try to setData in controller of Edit like old way (Form Block ) but not work with ui implement. – mrtuvn Nov 14 '16 at 6:54
  • yes beforesave item object not exist, so at that time you can use caption in form.xml to set init value in dropdown. – Rakesh Jesadiya Nov 14 '16 at 6:59
  • 1
    use <item name="caption" xsi:type="string" translate="true">-- Please Select --</item> for initial value set. – Rakesh Jesadiya Nov 14 '16 at 7:16
  • i will try it again and back with results – mrtuvn Nov 14 '16 at 8:34
  • Have you try with caption for default set of string in select box. – Rakesh Jesadiya Nov 15 '16 at 10:37
3

You can create a custom js component based on the one you are using. It is quite simple considering the example of the select component. We are using a collection's source model and our modules' ui-form.

Example of the component in the xml file (ui):

<fieldset name="general">
    <field name="methods">
        <argument name="data" xsi:type="array">
            <item name="options" xsi:type="object">MageWorx\ShippingRules\Model\Config\Source\Methods</item>
            <item name="config" xsi:type="array">
                <item name="dataType" xsi:type="string">text</item>
                <item name="formElement" xsi:type="string">select</item>
                <item name="component" xsi:type="string">MageWorx_ShippingRules/js/methods_select</item>
                <item name="dataScope" xsi:type="string">methods</item>
                <item name="source" xsi:type="string">mageworx_shippingrules_method_form</item>
            </item>
        </argument>
    </field>

A simple source model:

<?php
/**
 * Copyright © 2016 MageWorx. All rights reserved.
 * See LICENSE.txt for license details.
 */
namespace MageWorx\ShippingRules\Model\Config\Source;

class Methods implements \Magento\Framework\Option\ArrayInterface
{
    /**
     * @var \MageWorx\ShippingRules\Model\ResourceModel\Method\CollectionFactory
     */
    protected $methodCollectionFactory;

    /**
     * MethodRatePrice constructor.
     * @param \MageWorx\ShippingRules\Model\ResourceModel\Method\CollectionFactory $methodCollectionFactory
     */
    public function __construct(
        \MageWorx\ShippingRules\Model\ResourceModel\Method\CollectionFactory $methodCollectionFactory
    ) {
        $this->methodCollectionFactory = $methodCollectionFactory;
    }

    /**
     * @return array
     */
    public function toOptionArray()
    {
        /** @var \MageWorx\ShippingRules\Model\ResourceModel\Method\Collection $collection */
        $collection = $this->methodCollectionFactory->create();
        $options = [
            [
                'value' => '',
                'label' => __('Select value')
            ]
        ];
        $options = array_merge($options, $collection->toOptionArray());

        return $options;
    }
}

And the js component inherited from the default select:

define([
    'underscore',
    'mageUtils',
    'Magento_Ui/js/form/element/select'
], function (_, utils, Select) {
    'use strict';

    return Select.extend({

        /**
         * Extends instance with defaults, extends config with formatted values
         *     and options, and invokes initialize method of AbstractElement class.
         *     If instance's 'customEntry' property is set to true, calls 'initInput'
         */
        initialize: function () {
            this._super();

            var parser = document.createElement('a');
            parser.href = window.location.href;
            var path = parser.pathname;
            var clearPath = path.replace(/^(\/index\.php\/)|^\/|\/$/uig, "");
            var params = clearPath.split("/");
            var paramsObject = {};
            for (var i = 0; i < params.length; i++) {
                if (i < 4) {
                    delete params[i];
                    continue;
                }
                if (typeof params[i] == 'undefined' || typeof params[i + 1] == 'undefined') {
                    continue;
                }
                paramsObject[params[i]] = params[i + 1];
                i++;
            }

            this.set('value', paramsObject.id);

            return this;
        }

    });
});

We've taken the base method to initialize the component. First, we've called its parental method that will do all the main work. Then, we've parsed the current address, separate into parameters and turned into an object. Next, we've taken the needed parameter (id) and set the value component equal to our parameter from an URL.

It looks like that in a browser window:

enter image description here

And during the next saving:

enter image description here

This code may be not perfect, but will guide you in the right direction. If you will manage to enhace it, please, wright your variant.

2

From both the comments and question I understand that problem is populating the form when a new entity is created not at edit.

The answer is really simple.

Structure your create url in the following manner:

www.website.[com|org|etc]/[admin]/[front-name]/[controller]/[action]/[requestFieldName]/0/[params ..]

Then when returning $loadedData from you DataProvider.

/**
     * @return array
     */
    public function getData()
    {
        //Perform some check that is new action
        $this->loadedData['0']['entity|fieldset-name] = $this-request->getParams()
        return $this-loadedData;
    }

Take into consideration the following:

  1. By default in Magento2 entity ids start from 1. So 0 will never match an existing entity id.

  2. The solution is independent of where from the params come. I gave this example because it was part of the question.

Hope it helps.

1

The issue caused by your input wrong requestFieldName. In your component file you find dataSource tag and check primaryFieldName is primary key of table and requestFieldName is value of param id on your url:

Example: The url: http://127.0.0.1/domain.com/admin/moduleName/controlerName/edit/param_id/1

In your component file: componentFileName_form.xml

In dataSource tag:

<dataSource name="componentFileName_form_data_source">
    <argument name="dataProvider" xsi:type="configurableObject">
        <argument name="class" xsi:type="string">Your_NameSpace\ModuleName\Model\ModelName\DataProvider</argument>
        <argument name="name" xsi:type="string">componentFileName_form_data_source</argument>
        <argument name="primaryFieldName" xsi:type="string">table_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="multivendor/transactions/save"/>
            </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>

Please notice that <argument name="primaryFieldName" xsi:type="string">table_id</argument> is primary key of your table and <argument name="requestFieldName" xsi:type="string">param_id</argument> is request param on url.

0

If I understand correctly, you need to set a default value for a field that is generated using ui-components.
If so, you can do that directly from the ui components xml file.
You can do that by setting the default option.

Here is an example:

   <field name="name">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="dataType" xsi:type="string">text</item>
                <item name="label" xsi:type="string" translate="true">Name</item>
                <item name="formElement" xsi:type="string">input</item>
                <item name="source" xsi:type="string">[source_here]</item>
                <item name="sortOrder" xsi:type="number">10</item>
                <item name="dataScope" xsi:type="string">name</item>
                <item name="validation" xsi:type="array">
                    <item name="required-entry" xsi:type="boolean">true</item>
                </item>
                <item name="default" xsi:type="string">your defalt value here</item><!-- this will set a default value -->
            </item>
        </argument>
    </field>
  • Can i pass value from registry or session to field in form component. Select field have options but i don't want to use default value. Seem Provider only fill exist data from collection and can't setdata right? Where is a good place for setData field – mrtuvn Oct 27 '16 at 5:43
  • It can be done, but you need to create a form modifier class that changes the ui component similar to this one for example Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AdvancedPricing, but I'm not 100% sure how you can do that. – Marius Oct 27 '16 at 5:44
  • I will give a try and back with result – mrtuvn Oct 27 '16 at 6:33
  • How i can set data to specific field. Example my file in form with config dataScope = data name_space=testform requestFieldName=id field name = field1 inside fieldset name = base_fieldset path to my field is $.data.id.base_fieldset.field1. Is it right? – mrtuvn Oct 27 '16 at 10:21
  • I think can't setdata in new form ui mechanism in normal way! In old school way. We can get-set form data and set data in controller. But seem in new ui-form can't do that in same way. Setdata use modifer seem very difficult to do and not necessary. I will find another way – mrtuvn Oct 28 '16 at 3:43

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.