Magento 2 dynamicRows as new tab for admin customer edit, how do you get data loaded?
-
14-04-2021 - |
Pergunta
How can I load the data from customer DataProvider plugin into my ui_component dynamicRows?
I have created a new tab in the admin customer edit form, and added my ui_component, which seems to work well. But I can't populate the data already stored in my database.
I have tried to add xml for DataSource, but I think that has conflict with original customer_form.xml DataSource "customer_form.customer_form_data_source" because when I add DataSource, the page no longer loads.
dataSource XML:
<dataSource name="mycustomrows">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">MyVendor\MyModule\Model\Customer\DataProvider</argument>
<argument name="primaryFieldName" xsi:type="string">id</argument>
<argument name="requestFieldName" xsi:type="string">id</argument>
<argument name="meta" xsi:type="array">
<item name="mycustomrows" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string" translate="true">My Custom Rows</item>
</item>
</item>
</argument>
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
</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>
dataProvider for dataSource:
<?php
namespace MyVendor\MyModule\Model\Customer;
class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
protected $loadedData;
protected $collectionFactory;
public function __construct(
$name,
$primaryFieldName,
$requestFieldName,
\MyVendor\MyModule\Model\ResourceModel\Row\Collection $collection,
\MyVendor\MyModule\Model\ResourceModel\Row\CollectionFactory $collectionFactory,
array $meta = [],
array $data = []
) {
$this->collection = $collection;
$this->collectionFactory = $collectionFactory;
parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
}
public function getData()
{
if (isset($this->loadedData)) {
return $this->loadedData;
}
$collection = $this->collectionFactory->create();
// add Filter for Customer ID
//->setOrder('position', 'ASC');
$items = $collection->getItems();
foreach ($items as $item) {
$this->loadedData[$item->getId()] = $item->getData();
}
return $this->loadedData;
}
}
I believe the data has to be loaded with Plugin for "Magento\Customer\Model\Customer\DataProvider" as I am doing below, but I can't seem to get populate rows on load.
view/adminhtml/ui_component/customer_form.xml
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<fieldset name="mycustomrows">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string" translate="true">My Custom Rows</item>
<item name="sortOrder" xsi:type="number">10</item>
</item>
</argument>
<dynamicRows name="mycustomrows">
<settings>
<addButtonLabel translate="true">Add Row</addButtonLabel>
<additionalClasses>
<class name="admin__field-wide">true</class>
</additionalClasses>
<componentType>dynamicRows</componentType>
</settings>
<container name="record" component="Magento_Ui/js/dynamic-rows/record">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="isTemplate" xsi:type="boolean">true</item>
<item name="is_collection" xsi:type="boolean">true</item>
<item name="componentType" xsi:type="string">container</item>
<item name="positionProvider" xsi:type="string">position</item>
</item>
</argument>
<field name="mycustomrows_select1" formElement="select" sortOrder="10">
<settings>
<dataType>text</dataType>
<label translate="true">Select Field 1</label>
<disabled>false</disabled>
<dataScope>mycustomrows_select1</dataScope>
</settings>
<formElements>
<select>
<settings>
<options class="MyVendor\MyModule\Model\Source\SelectFieldOne"/>
</settings>
</select>
</formElements>
</field>
<field name="mycustomrows_input1" sortOrder="20" formElement="input">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="source" xsi:type="string">customer</item>
</item>
</argument>
<settings>
<label translate="true">Text Field 1</label>
<dataType>text</dataType>
<dataScope>mycustomrows_text1</dataScope>
</settings>
</field>
<actionDelete sortOrder="30">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="componentType" xsi:type="string">actionDelete</item>
<item name="dataType" xsi:type="string">text</item>
<item name="fit" xsi:type="boolean">false</item>
<item name="label" xsi:type="string">Actions</item>
<item name="sortOrder" xsi:type="string">500</item>
<item name="additionalClasses" xsi:type="string">data-grid-actions-cell</item>
<item name="template" xsi:type="string">Magento_Backend/dynamic-rows/cells/action-delete</item>
</item>
</argument>
</actionDelete>
</container>
</dynamicRows>
</fieldset>
</form>
etc/adminhtml/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Customer\Model\Customer\DataProvider">
<plugin name="customer_get_mycustomrows" type="MyVendor\MyModule\Model\Customer\DataProvider" sortOrder="5" />
</type>
</config>
Model/Customer/DataProvider.php
<?php
namespace MyVendor\MyModule\Model\Customer;
class DataProvider
{
protected $collection;
protected $collectionFactory;
protected $loadedData;
public function __construct(
\MyVendor\MyModule\Model\ResourceModel\Row\Collection $collection,
\MyVendor\MyModule\Model\ResourceModel\Row\CollectionFactory $collectionFactory,
array $data = []
) {
$this->collection = $collection;
$this->collectionFactory = $collectionFactory;
}
public function afterGetData(\Magento\Customer\Model\Customer\DataProvider $subject, $result)
{
if($result){
$customer_id = key($result);
$customerData = $result[$customer_id]['customer'];
if(is_null($this->loadedData)) {
$this->loadedData = array();
$collection = $this->collectionFactory->create(); //->setOrder('position', 'ASC');
$items = $collection->getItems();
foreach ($items as $item) {
$this->loadedData[] = $item->getData();
}
}
$result[$customer_id]['customer']["mycustomrows"] = $this->loadedData;
}
return $result;
}
}
I can't seem to get any records populated when I load a customer edit page.
Solução
You need to change in the last two steps,
Step-1, you need to add a plugin
for DataProviderWithDefaultAddresses
in place of DataProvider,
etc/adminhtml/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Customer\Model\Customer\DataProviderWithDefaultAddresses">
<plugin name="customer_get_mycustomrows" type="MyVendor\MyModule\Model\Customer\DataProvider" sortOrder="5" />
</type>
</config>
And in below class use DataProviderWithDefaultAddresses
as a subject in the argument,
Model/Customer/DataProvider.php
<?php
namespace MyVendor\MyModule\Model\Customer;
class DataProvider
{
protected $collection;
protected $collectionFactory;
protected $loadedData;
public function __construct(
\MyVendor\MyModule\Model\ResourceModel\Row\Collection $collection,
\MyVendor\MyModule\Model\ResourceModel\Row\CollectionFactory $collectionFactory,
array $data = []
) {
$this->collection = $collection;
$this->collectionFactory = $collectionFactory;
}
public function afterGetData(\Magento\Customer\Model\Customer\DataProviderWithDefaultAddresses $subject, $result)
{
if($result){
$customer_id = key($result);
$customerData = $result[$customer_id]['customer'];
if(is_null($this->loadedData)) {
$this->loadedData = array();
$collection = $this->collectionFactory->create(); //->setOrder('position', 'ASC');
$items = $collection->getItems();
foreach ($items as $item) {
$this->loadedData[] = $item->getData();
}
}
$result[$customer_id]['customer']["mycustomrows"] = $this->loadedData;
}
return $result;
}
}
After run compile command and clear cache data will be loaded into edit form.
Outras dicas
This will load custom collection in dynamic rows:
customer_form.xml
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<fieldset name="customdata">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string" translate="true">Custom data</item>
<item name="sortOrder" xsi:type="number">1</item>
</item>
</argument>
<container name="customdata">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/dynamic-rows/dynamic-rows</item>
<item name="template" xsi:type="string">ui/dynamic-rows/templates/default</item>
<item name="componentType" xsi:type="string">dynamicRows</item>
<item name="recordTemplate" xsi:type="string">record</item>
<item name="addButtonLabel" xsi:type="string">Add new</item>
<item name="deleteProperty" xsi:type="boolean">false</item>
<item name="additionalClasses" xsi:type="array">
<item name="admin__field-wide" xsi:type="boolean">true</item>
</item>
</item>
</argument>
<container name="record">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string" translate="true">Custom data</item>
<item name="component" xsi:type="string" translate="true">Magento_Ui/js/dynamic-rows/record</item>
<item name="isTemplate" xsi:type="boolean">true</item>
<item name="is_collection" xsi:type="boolean">true</item>
<item name="showFallbackReset" xsi:type="boolean">false</item>
</item>
</argument>
<field formElement="input" name="field" sortOrder="90">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="source" xsi:type="string">Data</item>
</item>
</argument>
<settings>
<dataType>text</dataType>
<label translate="true">Field</label>
<dataScope>field</dataScope>
<validation>
<rule name="required-entry" xsi:type="boolean">true</rule>
</validation>
</settings>
</field>
</container>
</container>
</fieldset>
</form>
DataProvider.php
protected $collection;
protected $collectionFactory;
protected $loadedData;
public function __construct(
\Vendor\Vendor\Model\ResourceModel\Vendor\Collection $collection,
\Vendor\Vendor\Model\ResourceModel\Vendor\CollectionFactory $collectionFactory,
array $data = []
) {
$this->collection = $collection;
$this->collectionFactory = $collectionFactory;
}
public function afterGetData(\Magento\Customer\Model\Customer\DataProviderWithDefaultAddresses $subject, $result)
{
if ($result)
{
$customer_id = key($result);
$customerData = $result[$customer_id]['customer'];
if (is_null($this->loadedData))
{
$this->loadedData = [];
$collection = $this->collectionFactory->create();
$items = $collection->getItems();
foreach ($items as $item)
{
$result[$customer_id]["customdata"]["customdata"][] = $item->getData();
}
}
}
return $result;
}
di.xml
<type name="Magento\Customer\Model\Customer\DataProviderWithDefaultAddresses">
<plugin name="customdata" type="Vendor\Vendor\Model\Customer\DataProvider" sortOrder="5" />
</type>