Question

I have created a UI form with field catalog rule conditions. The form loads display the conditions section and it is saved in the table. But in edit case the conditions are not displayed.

Reference: https://www.mageworx.com/blog/2016/09/magento-2-module-with-conditions-model-fieldset/

Please help me to resolve this. Here is my code

Installschema.php

 public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;
        $contextInterface = $context;
        $installer->startSetup();

        $table = $installer->getConnection()->newTable(
            $installer->getTable('example_label')
        )->addColumn(
            'label_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['identity' => true, 'nullable' => false, 'primary' => true],
            'ID'
        )->addColumn(
            'name',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            ['nullable' => false],
            'Name'
        )->addColumn(
            'conditions_serialized',
            Table::TYPE_TEXT,
            '4G',
            [],
            'Conditions Serialized'
        )->addIndex(
            $installer->getIdxName('example_label', ['name']),
            ['name']
        )->setComment('example_label Table');
        $installer->getConnection()->createTable($table);

     }

UI Form

<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">productlabel_form.productlabel_form_data_source</item>
            <item name="deps" xsi:type="string">productlabel_form.productlabel_form_data_source</item>
        </item>
        <item name="label" xsi:type="string" translate="true">Information</item>
        <item name="config" xsi:type="array">
            <item name="dataScope" xsi:type="string">data</item>
            <item name="namespace" xsi:type="string">productlabel_form</item>
        </item>
        <item name="buttons" xsi:type="array">
            <item name="save" xsi:type="string">Vendor\ProductLabel\Block\Adminhtml\Productlabel\Edit\Button\Save</item>           
        </item>
    </argument>
    <settings>
        <layout>
            <navContainerName>left</navContainerName>
            <type>tabs</type>
        </layout>
        <deps>
            <dep>productlabel_form.productlabel_form_data_source</dep>
        </deps>
    </settings>
    <dataSource name="productlabel_form_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">Vendor\ProductLabel\Model\ResourceModel\Productlabel\DataProvider</argument>
            <argument name="name" xsi:type="string">productlabel_form_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">label_id</argument>
            <argument name="requestFieldName" xsi:type="string">label_id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="submit_url" xsi:type="url" path="productlabel/productlabel/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>
    <fieldset name="productlabel_details">
        <settings>
            <label translate="true">Details</label>
        </settings>

        <field name="label_id">
         <argument name="data" xsi:type="array">
             <item name="config" xsi:type="array">
                 <item name="visible" xsi:type="boolean">false</item>
                 <item name="dataType" xsi:type="string">text</item>
                 <item name="formElement" xsi:type="string">input</item>
                 <item name="source" xsi:type="string">label_id</item>
             </item>
         </argument>
        </field>  
        <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">name</item>
                    <item name="dataScope" xsi:type="string">name</item>
                    <item name="required" xsi:type="boolean">true</item>
                    <item name="validation" xsi:type="array">
                            <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                </item>
            </argument>
        </field>       


    </fieldset>
    <fieldset name="conditions_fieldset">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string" translate="true">Conditions</item>
                <item name="collapsible" xsi:type="boolean">false</item>
            </item>
        </argument>
        <container name="conditions_serialized_container" >
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="sortOrder" xsi:type="number">10</item>
                </item>
            </argument>
            <htmlContent name="html_content">
                <argument name="block" xsi:type="object">Vendor\ProductLabel\Block\Adminhtml\Productlabel\Edit\Tab\Conditions</argument>
            </htmlContent>
        </container>
    </fieldset>
</form>

Conditions.php

use Magento\Framework\App\ObjectManager;

class Conditions extends \Magento\Backend\Block\Widget\Form\Generic 
{

    protected $_rendererFieldset;


    protected $_conditions;

    protected $_nameInLayout = 'conditions';

    private $ruleFactory;

    private $labelFactory;


    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Data\FormFactory $formFactory,
        \Magento\Rule\Block\Conditions $conditions,
        \Magento\Backend\Block\Widget\Form\Renderer\Fieldset $rendererFieldset,
        \Vendor\ProductLabel\Model\ProductlabelFactory $labelFactory,
        array $data = []
    ) {
        $this->_rendererFieldset = $rendererFieldset;
        $this->_conditions = $conditions;
        $this->labelFactory = $labelFactory;
        parent::__construct($context, $registry, $formFactory, $data);
    }


    private function getRuleFactory()
    {
        if ($this->ruleFactory === null) {
            $this->ruleFactory = ObjectManager::getInstance()->get('Magento\CatalogRule\Model\RuleFactory');
        }
        return $this->ruleFactory;
    }

    public function getTabClass()
    {
        return null;
    }


    public function getTabUrl()
    {
        return null;
    }

    public function isAjaxLoaded()
    {
        return false;
    }


    public function getTabLabel()
    {
        return __('Conditions');
    }


    public function getTabTitle()
    {
        return __('Conditions');
    }

    public function canShowTab()
    {
        return true;
    }


    public function isHidden()
    {
        return false;
    }


    protected function _prepareForm()
    {
        $model = $this->_coreRegistry->registry('current_label');
        $form = $this->addTabToForm($model);
        $this->setForm($form);

        return parent::_prepareForm();
    }


    protected function addTabToForm($model, $fieldsetId = 'conditions_serialized_field', $formName = 'productlabel_form')
    {
        if (!$model) {
            $id = $this->getRequest()->getParam('id');
            $model = $this->getRuleFactory()->create();
            $model->load($id);
        }
        $conditionsFieldSetId = $model->getConditionsFieldSetId($formName);
        $newChildUrl = $this->getUrl(
            'catalog_rule/promo_catalog/newConditionHtml/form/' . $conditionsFieldSetId,
            ['form_namespace' => $formName]
        );


        /** @var \Magento\Framework\Data\Form $form */
        $form = $this->_formFactory->create();
        $form->setHtmlIdPrefix('rule_');
        $renderer = $this->_rendererFieldset->setTemplate(
            'Magento_CatalogRule::promo/fieldset.phtml'
        )->setNewChildUrl(
            $newChildUrl
        );


        $fieldset = $form->addFieldset(
            $fieldsetId,
            [
                'legend' => __(
                    'Apply the rule only if the following conditions are met (leave blank for all products).'
                )
            ]
        )->setRenderer(
            $renderer
        );
        $fieldset->addField(
            'conditions',
            'text',
            [
                'name'           => 'conditions',
                'label'          => __('Conditions'),
                'title'          => __('Conditions'),
                'required'       => true,
                'data-form-part' => $formName
            ]
        )->setRule(
            $model
        )->setRenderer(
            $this->_conditions
        );

        $form->setValues($model->getData());

        $this->setConditionFormName($model->getConditions(), $formName);
        return $form;
    }

     private function setConditionFormName(\Magento\Rule\Model\Condition\AbstractCondition $conditions, $formName)
    {
        $conditions->setFormName($formName);
        if ($conditions->getConditions() && is_array($conditions->getConditions())) {
            foreach ($conditions->getConditions() as $condition) {
                $this->setConditionFormName($condition, $formName);
            }
        }

Save Controller

public function execute()
    {
        $resultRedirect = $this->resultRedirectFactory->create();
        $data = $this->getRequest()->getPostValue();
        if ($data) {


            if(isset($data['rule'])){
                $dataArray['conditions_serialized'] = $this->serializer->serialize($data['rule']['conditions']);
            }
            $dataArray['name'] = $data['productlabel_details']['name'];


            $label = $this->labelDataFactory->create();
            $this->dataObjectHelper->populateWithArray(
                $label,
                $dataArray,
                '\Vendor\ProductLabel\Api\Data\ProductlabelInterface'
            );
            try {                
                $labelInterface = $this->labelRepository->save($label);
                $this->_getSession()->setFormData(false);
                $this->messageManager->addSuccess(__('You saved the item.'));                
                return $resultRedirect->setPath('*/*/');
            } catch (\Exception $e) {

            }
        }
        return $resultRedirect->setPath('*/*/');
    }

Edit Controller

 public function execute()
    {
        $id = $this->getRequest()->getParam('label_id');
        $model = $this->labelFactory->create();   

        if ($id) {
            $model->load($id);                        
            if (!$model->getId()) {                
                $resultRedirect = $this->resultRedirectFactory->create();
                return $resultRedirect->setPath('*/*/');
            }

        }

        $data = $this->_session->getPageData(true);
        if (!empty($data)) {
            $model->addData($data);
        }

        $model->getConditions()->setJsFormObject('conditions_serialized_field');

        $this->coreRegistry->register('current_label', $model);

        $resultPage = $this->resultPageFactory->create();

        $this->initPage($resultPage)->addBreadcrumb(
            $id ? __('Edit Product Label') : __('New  Label'),
            $id ? __('Edit Product Label') : __('New  Label')
        );
        $resultPage->getConfig()->getTitle()->prepend(__(' labels'));
        $resultPage->getConfig()->getTitle()->prepend($id? ('Edit  Label') : __('New  Label'));
        return $resultPage;
    }
Was it helpful?

Solution 2

I have fixed the issue by changing the save function.

Conditions Block

    use Magento\Backend\Block\Widget\Tab\TabInterface;
    use Magento\Backend\Block\Widget\Form\Generic;

    class Conditions extends Generic implements TabInterface
    {



  protected $rendererFieldset;

    protected $conditions;

    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Data\FormFactory $formFactory,
        \Magento\Rule\Block\Conditions $conditions,
        \Magento\Backend\Block\Widget\Form\Renderer\Fieldset $rendererFieldset,
        \Vendor\ProductLabel\Model\ProductlabelFactory $labelFactory,
        array $data = []
    ) {
        $this->rendererFieldset = $rendererFieldset;
        $this->conditions = $conditions;
        $this->labelFactory = $labelFactory;
        parent::__construct($context, $registry, $formFactory, $data);
    }

     public function getTabLabel()
    {
        return __('Conditions');
    }

    public function getTabTitle()
    {
        return __('Conditions');
    }

    public function canShowTab()
    {
        return true;
    }

    public function isHidden()
    {
        return false;
    }

    protected function _prepareForm()
    {
        $model = $this->_coreRegistry->registry('current_label');
        $form = $this->addTabToForm($model);
        $this->setForm($form);
        return parent::_prepareForm();
    }


    protected function addTabToForm($model, $fieldsetId = 'conditions_fieldset', $formName = 'productlabel_form')
    {
        if (!$model) {
            $id = $this->getRequest()->getParam('id');
            $model = $this->labelFactory->create();
            $model->load($id);
        }

        $newChildUrl = $this->getUrl('productlabel/productlabel/newConditionHtml/form/rule_conditions_fieldset');

        /** @var \Magento\Framework\Data\Form $form */
        $form = $this->_formFactory->create();
        $form->setHtmlIdPrefix('rule_');
        $renderer = $this->rendererFieldset->setTemplate(
            'Magento_CatalogRule::promo/fieldset.phtml'
        )->setNewChildUrl(
            $newChildUrl
        );

        $fieldset = $form->addFieldset(
            $fieldsetId,
            [
                'legend' => __(
                    'Apply the rule only if the following conditions are met (leave blank for all products).'
                )
            ]
        )->setRenderer(
            $renderer
        );
        $fieldset->addField(
            'conditions',
            'text',
            [
                'name'           => 'conditions',
                'label'          => __('Conditions'),
                'title'          => __('Conditions'),
                'required'       => true,
                'data-form-part' => $formName
            ]
        )->setRule(
            $model
        )->setRenderer(
            $this->conditions
        );

        $form->setValues($model->getData());

        $this->setConditionFormName($model->getConditions(), $formName);
        return $form;
    }


    private function setConditionFormName(\Magento\Rule\Model\Condition\AbstractCondition $conditions, $formName)
    {
        $conditions->setFormName($formName);
        if ($conditions->getConditions() && is_array($conditions->getConditions())) {
            foreach ($conditions->getConditions() as $condition) {
                $this->setConditionFormName($condition, $formName);
            }
        }
    }
}

NewConditionHtml Controller

namespace Vendor\ProductLabel\Controller\Adminhtml\Productlabel;

class NewConditionHtml extends \Vendor\ProductLabel\Controller\Adminhtml\Productlabel
{


     public function execute()
    {
        $id = $this->getRequest()->getParam('id');
        $labelFactory = $this->_objectManager->create('Vendor\ProductLabel\Model\ProductlabelFactory');
        $typeArr = explode('|', str_replace('-', '/', $this->getRequest()->getParam('type')));
        $type = $typeArr[0];
        $model = $this->_objectManager->create(
            $type
        )->setId(
            $id
        )->setType(
            $type
        )->setRule(
            $labelFactory->create()
        )->setPrefix(
            'conditions'
        );

        if (!empty($typeArr[1])) {
            $model->setAttribute($typeArr[1]);
        }

        if ($model instanceof \Magento\Rule\Model\Condition\AbstractCondition) {
            $model->setFormName('productlabel_form')->setJsFormObject('conditions_fieldset');
            $html = $model->asHtmlRecursive();
        } else {
            $html = '';
        }
        $this->getResponse()->setBody($html);
    }
}

Save Controller

class Save extends \Vendor\ProductLabel\Controller\Adminhtml\Productlabel
{

    private $productModel;
    private $labelFactory;
    protected $imageUploader;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Registry $registry,
        \Vendor\ProductLabel\Model\ProductlabelFactory $labelFactory,
        \Magento\Catalog\Model\Product $product
    ) {
        $this->labelFactory = $labelFactory;
        $this->productModel = $product;
        parent::__construct($context, $registry);
    }


    public function execute()
    {
        $resultRedirect = $this->resultRedirectFactory->create();
        $data = $this->getRequest()->getPostValue();

        if ($data) {
            $model = $this->labelFactory->create();
            if(isset($data['productlabel_details']['label_id'])){
                $id = $data['productlabel_details']['label_id'];
                if ($id) {
                    $model->load($id);
                    $dataArray['id'] = $id;                    
                }
            }

            if(isset($data['rule'])){
                unset($data['rule']['conditions']['type']);
                unset($data['rule']['conditions']['value']);
                unset($data['rule']['conditions']['aggregator']);
                $dataArray['conditions'] = $data['rule']['conditions'];//$this->serializer->serialize
            }

            $dataArray['form_key'] = $data['form_key'];
            $dataArray['name'] = $data['productlabel_details']['name'];

            $model->loadPost($dataArray);
            try {                
                $model->save();
                $this->_getSession()->setFormData(false);
                $this->messageManager->addSuccess(__('You saved the item.'));
                if ($this->getRequest()->getParam('back')) {
                    return $resultRedirect->setPath('*/*/edit', ['label_id' => $model->getId()]);
                }
                return $resultRedirect->setPath('*/*/');
            } catch (\Exception $e) {
                $this->messageManager->addError($e->getMessage());
                $this->_getSession()->setFormData($data);
                return $resultRedirect->setPath(
                    '*/*/edit',
                    ['label_id' => $model->getId()]
                );
            }
        }
        return $resultRedirect->setPath('*/*/');
    }
}

OTHER TIPS

Try with below way :

In your data provider file set condition field value like below.

Vendor\ProductLabel\Model\ResourceModel\Productlabel\DataProvider

 "conditions_serialized_field" => $collectionData->getData('conditions_serialized_field')

I hope it works!

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top