- I wish to create a form in admin.
- The purpose of the form is not CRUD.
- Using blocks for creating forms is marked as deprecated in favor of ui_component forms
- Is it possible to use a ui component form without a data source?
Magento 2 – Use UI Form Component Without Data Source
magento2uicomponent
Related Solutions
So the way i ended up doing this was to use a form modifier for the data provider by using the Magento Catalog as a an example.
A modifier allows you to affect the meta or structure of the ui component json which is sent to the front end for rendering.
see Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Related.php
In order to filter the listing by the item id for what you are editing on the form, set a filter on the collection in the data provider for the listing using the request param for the form id. Then make sure in the get meta you set the imports and exports arrays with the following substituting the id for your id:
'imports' => [
'seeminglyArbitraryValue' => '${ $.provider }:data.form_id_field_name'
],
'exports' => [
'seeminglyArbitraryValue' => '${ $.externalProvider }:params.form_id_field_name'
],
Using dataPersistor to get Form data, thought you're using getSession
$data = $this->getSession()->getFormData();
Save action
<?php
namespace Vendor\Module\Controller\Adminhtml\Scheduler;
use Magento\Framework\Exception\LocalizedException;
class Save extends \Magento\Backend\App\Action
{
protected $dataPersistor;
/**
* @param \Magento\Backend\App\Action\Context $context
* @param \Magento\Framework\App\Request\DataPersistorInterface $dataPersistor
*/
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\App\Request\DataPersistorInterface $dataPersistor
) {
$this->dataPersistor = $dataPersistor;
parent::__construct($context);
}
/**
* Save actionSave action
*
* @return \Magento\Framework\Controller\ResultInterface
*/
public function execute()
{
/** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
$resultRedirect = $this->resultRedirectFactory->create();
$data = $this->getRequest()->getPostValue();
if ($data) {
$id = $this->getRequest()->getParam('scheduler_id');
$model = $this->_objectManager->create('Vendor\Module\Model\Scheduler')->load($id);
if (!$model->getId() && $id) {
$this->messageManager->addErrorMessage(__('This Scheduler no longer exists.'));
return $resultRedirect->setPath('*/*/');
}
$model->setData($data);
try {
$model->save();
$this->messageManager->addSuccessMessage(__('You saved the Scheduler.'));
$this->dataPersistor->clear('engraving_scheduler');
if ($this->getRequest()->getParam('back')) {
return $resultRedirect->setPath('*/*/edit', ['scheduler_id' => $model->getId()]);
}
return $resultRedirect->setPath('*/*/');
} catch (LocalizedException $e) {
$this->messageManager->addErrorMessage($e->getMessage());
} catch (\Exception $e) {
$this->messageManager->addExceptionMessage($e, __('Something went wrong while saving the Scheduler.'));
}
$this->dataPersistor->set('engraving_scheduler', $data);
return $resultRedirect->setPath('*/*/edit', ['scheduler_id' => $this->getRequest()->getParam('scheduler_id')]);
}
return $resultRedirect->setPath('*/*/');
}
}
DataProvider
<?php
namespace Vendor\Module\Model\Scheduler;
use Vendor\Module\Model\ResourceModel\Scheduler\CollectionFactory;
use Magento\Framework\App\Request\DataPersistorInterface;
class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
protected $dataPersistor;
protected $loadedData;
protected $collection;
/**
* Constructor
*
* @param string $name
* @param string $primaryFieldName
* @param string $requestFieldName
* @param CollectionFactory $collectionFactory
* @param DataPersistorInterface $dataPersistor
* @param array $meta
* @param array $data
*/
public function __construct(
$name,
$primaryFieldName,
$requestFieldName,
CollectionFactory $collectionFactory,
DataPersistorInterface $dataPersistor,
array $meta = [],
array $data = []
) {
$this->collection = $collectionFactory->create();
$this->dataPersistor = $dataPersistor;
parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
}
/**
* Get data
*
* @return array
*/
public function getData()
{
if (isset($this->loadedData)) {
return $this->loadedData;
}
$items = $this->collection->getItems();
foreach ($items as $model) {
$this->loadedData[$model->getId()] = $model->getData();
}
$data = $this->dataPersistor->get('engraving_scheduler');
if (!empty($data)) {
$model = $this->collection->getNewEmptyItem();
$model->setData($data);
$this->loadedData[$model->getId()] = $model->getData();
$this->dataPersistor->clear('engraving_scheduler');
}
return $this->loadedData;
}
}
ui form xml
<?xml version="1.0" ?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">engraving_scheduler_form.scheduler_form_data_source</item>
<item name="deps" xsi:type="string">engraving_scheduler_form.scheduler_form_data_source</item>
</item>
<item name="label" translate="true" xsi:type="string">General Information</item>
<item name="config" xsi:type="array">
<item name="dataScope" xsi:type="string">data</item>
<item name="namespace" xsi:type="string">engraving_scheduler_form</item>
</item>
<item name="template" xsi:type="string">templates/form/collapsible</item>
<item name="buttons" xsi:type="array">
<item name="back" xsi:type="string">Vendor\Module\Block\Adminhtml\Scheduler\Edit\BackButton</item>
<item name="delete" xsi:type="string">Vendor\Module\Block\Adminhtml\Scheduler\Edit\DeleteButton</item>
<item name="save" xsi:type="string">Vendor\Module\Block\Adminhtml\Scheduler\Edit\SaveButton</item>
<item name="save_and_continue" xsi:type="string">Vendor\Module\Block\Adminhtml\Scheduler\Edit\SaveAndContinueButton</item>
</item>
</argument>
<dataSource name="scheduler_form_data_source">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">Vendor\Module\Model\Scheduler\DataProvider</argument>
<argument name="name" xsi:type="string">scheduler_form_data_source</argument>
<argument name="primaryFieldName" xsi:type="string">scheduler_id</argument>
<argument name="requestFieldName" xsi:type="string">scheduler_id</argument>
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="submit_url" path="*/*/save" xsi:type="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>
<fieldset name="General">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string"/>
</item>
</argument>
<field name="label">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">text</item>
<item name="label" translate="true" xsi:type="string">Title</item>
<item name="formElement" xsi:type="string">input</item>
<item name="source" xsi:type="string">Scheduler</item>
<item name="sortOrder" xsi:type="number">10</item>
<item name="dataScope" xsi:type="string">label</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">true</item>
</item>
</item>
</argument>
</field>
</fieldset>
</form>
Best Answer
From my digging it turns out the data provider is required.
I just implemented a dummy data provider.
I had to override both methods that work with $collection member to avoid errors.