2

I have created a form using UI component, This form has a select dropdown which displays option related to current entity id if form is in edit mode and all options if a new entity is being added by form.

UI Form

<fieldset name="EntityFields">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="label" xsi:type="string" translate="true"></item>
        </item>
    </argument>

    <!-- This field represents form id and is hidden -->
    <field name="question_id">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">                    
                <item name="dataType" xsi:type="string">text</item>
                <item name="formElement" xsi:type="string">input</item>
                <item name="source" xsi:type="string">questionmanager_entity</item>
                <item name="visible" xsi:type="boolean">false</item>
            </item>
        </argument>
    </field>
    <field name="question_type">
        <argument name="data" xsi:type="array">
            <item name="options" xsi:type="object">Ricky\QuestionManager\Model\UiForm\TypeList\Options</item>
            <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Ricky_QuestionManager\js\form\element\options</item>
                <item name="dataScope" xsi:type="string">question_type</item>
                <item name="dataType" xsi:type="string">text</item>
                <item name="default" xsi:type="string">0</item>
                <item name="formElement" xsi:type="string">select</item>
                <item name="label" xsi:type="string" translate="true">Question Type</item>
                <item name="notice" xsi:type="string" translate="true">Question will use Field type on store front according to selected Question type.</item>
                <item name="required" xsi:type="boolean">true</item>
                <item name="sortOrder" xsi:type="number">30</item>
                <item name="validation" xsi:type="array">
                    <item name="required-entry" xsi:type="boolean">true</item>
                </item>
            </item>
        </argument>
    </field>
</fieldset>

I want to pass current question id to following class (* if form is in edit mode)

<item name="options" xsi:type="object">Ricky\QuestionManager\Model\UiForm\TypeList\Options</item>

*Edit This is my option class

class Options implements OptionSourceInterface
{

/**
 * Product collection
 *
 * @var \Ricky\QuestionManager\Model\ResourceModel\Question\Collection
 */
protected $collection;

/**
 * Construct
 *
 * @param CollectionFactory $collectionFactory
 */
public function __construct(
    CollectionFactory $collectionFactory
) {
    $this->collection = $collectionFactory->create();
}

/**
 * Get options
 *
 * @return array
 */
public function toOptionArray()
{
    foreach ($this->collection as $type) {
        $optionList[] = [
            'label' => $type->getTitle(),
            'value' => $type->getQuestionId(),
            'is_active' => $type->getIsDeleted()?false:true,
        ];
    }
    //echo "<pre>";print_r($optionList);exit;
    return $optionList;
}
}

Thankyou for you suggestion ans answer. :)

3
  • You can directly get the question id in your options class. Commented Mar 22, 2019 at 13:49
  • You need to just check the which action has called in your options class. Commented Mar 22, 2019 at 13:49
  • @DharmendraJadav, I have updated my question with option class. can you please explain me how can i get question id there? Commented Mar 25, 2019 at 4:46

2 Answers 2

0

Please check below options class which you have need to change.

class Options implements OptionSourceInterface 
{

/**
 * Http Request class
 *
 * @var \Magento\Framework\App\Request\Http
 */
protected $request;

/**
 * Product collection
 *
 * @var \Ricky\QuestionManager\Model\ResourceModel\Question\Collection
 */
protected $collection;

/**
 * Construct
 *
 * @param CollectionFactory $collectionFactory
 */
public function __construct(
    CollectionFactory $collectionFactory,
    \Magento\Framework\App\Request\Http $request
) {
    $this->collection = $collectionFactory->create();
    $this->request = $request;
}

/**
 * Get options
 *
 * @return array
 */
public function toOptionArray()
{
    $questionId = $this->request->getParam('question_id', false);

    if($questionId) {
        //Your Code which you want
    } else {
        foreach ($this->collection as $type) {
            $optionList[] = [
                'label' => $type->getTitle(),
                'value' => $type->getQuestionId(),
                'is_active' => $type->getIsDeleted()?false:true,
            ];
        }
    }


    //echo "<pre>";print_r($optionList);exit;
    return $optionList;
}
}

Change as per id which you have passed in url and update code as per your need.

Thanks

4
  • Yes I already used this approach from magento.stackexchange.com/questions/154134/… ..... by the way thanks. Commented Mar 25, 2019 at 5:37
  • Welcom any time Commented Mar 25, 2019 at 5:40
  • Accept answer if it's useful. Commented Mar 25, 2019 at 5:41
  • You didn't really read the question, did you? Commented Aug 18, 2021 at 4:07
2

Yes and no. The above suggestions will certainly work for retrieving parameters sent in the request, but does nothing for those of us who are looking to pass a parameter via the form XML (as the initial question asked and I was looking to replicate) when making a call to the Source's toOptionArray() method.

After a lot of "searching" for potential solutions, the answer presented itself once I dug into the original Magento class Magento\Ui\Component\Form\Element\AbstractOptionsField::prepare() method. Here we see that the toOptionArray() is called for the provided source class, with no parameters considered.

public function prepare()
{
    $config = $this->getData('config');
    if (isset($this->options)) {
        if (!isset($config['options'])) {
            $config['options'] = [];
        }
        if ($this->options instanceof OptionSourceInterface) {
            $options = $this->options->toOptionArray();
        } else {
            $options = array_values($this->options);
        }
        if (empty($config['rawOptions'])) {
            $options = $this->convertOptionsValueToString($options);
        }
        foreach ($options as &$option) {
            //Options contain static or dynamic entity data that is not supposed to contain templates.
            $option = $this->sanitizer->sanitize($option);
        }

        $config['options'] = array_values(array_replace_recursive($config['options'], $options));
    }
    $this->setData('config', (array)$config);
    parent::prepare();
}

To accomplish the desired functionality, extending this method is the only real option in this context. So I added a rewrite entry to my di.xml:

<preference for="Magento\Ui\Component\Form\Element\Select" type="<Vendor>\<Module>\Ui\Component\Form\Element\Select" />

and added this to my field "config" array:

<item name="options_params" xsi:type="array">
    <item name="parameter1" xsi:type="boolean">true</item>
    <item name="parameter2" xsi:type="boolean">true</item>
</item>

Then, in my custom Select class, I rewrote the prepare() method, adding support for passing any parameters through to the toOptionArray() as desired:

// Accept parameters to pass thru toOptionArray()
...
$optionParams = [];
if (isset($config['options_params'])) {
    $optionParams = $config['options_params'];
}

if ($this->options instanceof OptionSourceInterface) {
    $options = $this->options->toOptionArray($optionParams);
} else {
    $options = array_values($this->options);
}
...

Works like a charm. Hope it helps you too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.