How to setdata for field in form UI

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;
}

}

Another way to get data Using UI component.

If you want get dafault value from another module using UI component

Add this field in your custom_form.xml file

<item name="options" xsi:type="object">{Vendorname}\{Modulename}\Ui\Component\Form\Element\DataProvider</item>

In DataProvider.php file,

<?php
namespace {Vendorname}\{Modulename}\Ui\Component\Form\Element;
class DataProvider extends \Magento\Ui\Component\Form\Element\Input
{
  /**
     * Prepare component configuration
     *
     * @return void
     */
    public function prepare()
    {
      parent::prepare();

      $customValue = {Get Custom value};

      $config = $this->getData('config');

      if(isset($config['dataScope']) && $config['dataScope']=='your_field_id'){
        $config['default']= $customValue;
        $this->setData('config', (array)$config);
      }
    }
}

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.


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.