Add condition field like Catalog Price Rule in custom Ui component Form Magento 2 [Part-2]

Written by Mahesh Makwana

Apr 09, 2021

Add condition field like Catalog Price Rule in custom Ui component Form Magento 2 [Part-2]

In Add condition field like Catalog Price Rule in custom Ui component Form Magento 2 [Part-2]  section we will perform CRUD operation and also we learn how to check how many products match. If you don’t know about the previous part-1 section please click here.

In previous section we create admin grid and form. In custom_condition_form.xml form file at app/code/Dolphin/AddConditionFiled/view/adminhtml/ui_component uncomment below code:

<?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">
    <argument name="data" xsi:type="array">
        <item name="js_config" xsi:type="array">
            <item name="provider" xsi:type="string">custom_condition_form.custom_condition_listing_data_source</item>
            <item name="deps" xsi:type="string">custom_condition_form.custom_condition_listing_data_source</item>
        </item>
        <item name="label" xsi:type="string" translate="true">General Information</item>
        <item name="config" xsi:type="array">
            <item name="dataScope" xsi:type="string">data</item>
            <item name="namespace" xsi:type="string">custom_condition_form</item>
        </item>
        <item name="spinner" xsi:type="string">general_information</item>
        <item name="buttons" xsi:type="array">
            <item name="back" xsi:type="string">Dolphin\AddConditionFiled\Block\Adminhtml\Edit\Button\Back</item>
            <item name="delete" xsi:type="string">Dolphin\AddConditionFiled\Block\Adminhtml\Edit\Button\Delete</item>
            <item name="reset" xsi:type="string">Dolphin\AddConditionFiled\Block\Adminhtml\Edit\Button\Reset</item>
            <item name="save" xsi:type="string">Dolphin\AddConditionFiled\Block\Adminhtml\Edit\Button\Save</item>
        </item>
        <item name="template" xsi:type="string">templates/form/collapsible</item>
    </argument>
    ............................................................................................................

Now we are create form buttons for perform different operations.

Step-1: Create Generic.php at app/code/Dolphin/AddConditionFiled/Block/Adminhtml/Edit/Button

<?php

namespace Dolphin\AddConditionFiled\Block\Adminhtml\Edit\Button;

use Magento\Backend\Block\Widget\Context;
use Magento\Cms\Api\PageRepositoryInterface;

class Generic
{
    protected $context;
    protected $pageRepository;

    public function __construct(
        Context $context,
        PageRepositoryInterface $pageRepository
    ) {
        $this->context = $context;
        $this->pageRepository = $pageRepository;
    }

    public function getUrl($route = '', $params = [])
    {
        return $this->context->getUrlBuilder()->getUrl($route, $params);
    }
}

Step-2: Create Back.php at app/code/Dolphin/AddConditionFiled/Block/Adminhtml/Edit/Button

<?php

namespace Dolphin\AddConditionFiled\Block\Adminhtml\Edit\Button;

use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

class Back extends Generic implements ButtonProviderInterface
{
    public function getButtonData()
    {
        return [
            'label' => __('Back'),
            'on_click' => sprintf("location.href = '%s';", $this->getBackUrl()),
            'class' => 'back',
            'sort_order' => 10,
        ];
    }

    public function getBackUrl()
    {
        return $this->getUrl('*/*/');
    }
}

Step-3: Create Reset.php at app/code/Dolphin/AddConditionFiled/Block/Adminhtml/Edit/Button

<?php

namespace Dolphin\AddConditionFiled\Block\Adminhtml\Edit\Button;

use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

class Reset implements ButtonProviderInterface
{
    public function getButtonData()
    {
        return [
            'label' => __('Reset'),
            'class' => 'reset',
            'on_click' => 'location.reload();',
            'sort_order' => 30,
        ];
    }
}

Step-4: Create Delete.php at app/code/Dolphin/AddConditionFiled/Block/Adminhtml/Edit/Button

<?php

namespace Dolphin\AddConditionFiled\Block\Adminhtml\Edit\Button;

use Magento\Backend\Block\Widget\Context;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

class Delete extends Generic implements ButtonProviderInterface
{
    protected $context;

    public function __construct(
        Context $context
    ) {
        $this->context = $context;
    }

    public function getButtonData()
    {
        $data = [];
        $rule_id = $this->context->getRequest()->getParam('rule_id');
        if ($rule_id) {
            $data = [
                'label' => __('Delete'),
                'class' => 'delete',
                'on_click' => 'deleteConfirm(\'' . __(
                    'Are you sure you want to delete this?'
                ) . '\', \'' . $this->getDeleteUrl() . '\')',
                'sort_order' => 20,
            ];
        }
        return $data;
    }

    public function getDeleteUrl()
    {
        $rule_id = $this->context->getRequest()->getParam('rule_id');
        return $this->getUrl('*/*/delete', ['rule_id' => $rule_id]);
    }
}

Step-5: Create Save.php at app/code/Dolphin/AddConditionFiled/Block/Adminhtml/Edit/Button

<?php

namespace Dolphin\AddConditionFiled\Block\Adminhtml\Edit\Button;

use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
use Magento\Ui\Component\Control\Container;

class Save extends Generic implements ButtonProviderInterface
{
    public function getButtonData()
    {
        return [
            'label' => __('Save'),
            'class' => 'save primary',
            'data_attribute' => [
                'mage-init' => [
                    'buttonAdapter' => [
                        'actions' => [
                            [
                                'targetName' => 'custom_condition_form.custom_condition_form',
                                'actionName' => 'save',
                                'params' => [
                                    false,
                                ],
                            ],
                        ],
                    ],
                ],
            ],
            'class_name' => Container::SPLIT_BUTTON,
            'options' => $this->getOptions(),
        ];
    }

    protected function getOptions()
    {
        $options[] = [
            'id_hard' => 'save_and_new',
            'label' => __('Save & New'),
            'data_attribute' => [
                'mage-init' => [
                    'buttonAdapter' => [
                        'actions' => [
                            [
                                'targetName' => 'custom_condition_form.custom_condition_form',
                                'actionName' => 'save',
                                'params' => [
                                    true,
                                    [
                                        'back' => 'add',
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];
        $options[] = [
            'id_hard' => 'save_and_close',
            'label' => __('Save & Close'),
            'data_attribute' => [
                'mage-init' => [
                    'buttonAdapter' => [
                        'actions' => [
                            [
                                'targetName' => 'custom_condition_form.custom_condition_form',
                                'actionName' => 'save',
                                'params' => [
                                    true,
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];
        return $options;
    }
}

After creating buttons form looking like below:

From With Buttons

After We Creating controller action file form perform CRUD operation.

Step-6: Create Rule.php at app/code/Dolphin/AddConditionFiled/Controller/Adminhtml/Index

<?php

namespace Dolphin\AddConditionFiled\Controller\Adminhtml\Index;

abstract class Rule extends \Magento\Backend\App\Action
{
    protected $coreRegistry = null;
    protected $fileFactory;
    protected $dateFilter;
    protected $ruleFactory;
    protected $logger;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Registry $coreRegistry,
        \Magento\Framework\App\Response\Http\FileFactory $fileFactory,
        \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter,
        \Dolphin\AddConditionFiled\Model\CustomConditionFactory $ruleFactory,
        \Psr\Log\LoggerInterface $logger
    ) {
        parent::__construct($context);
        $this->coreRegistry = $coreRegistry;
        $this->fileFactory = $fileFactory;
        $this->dateFilter = $dateFilter;
        $this->ruleFactory = $ruleFactory;
        $this->logger = $logger;
    }

    protected function _initRule()
    {
        $rule = $this->ruleFactory->create();
        $this->coreRegistry->register(
            'current_rule',
            $rule
        );
        $id = (int) $this->getRequest()->getParam('id');

        if (!$id && $this->getRequest()->getParam('rule_id')) {
            $id = (int) $this->getRequest()->getParam('rule_id');
        }

        if ($id) {
            $this->coreRegistry->registry('current_rule')->load($id);
        }
    }

    protected function _initAction()
    {
        $this->_view->loadLayout();
        return $this;
    }

}

Step-7: Create NewActionHtml.php at app/code/Dolphin/AddConditionFiled/Controller/Adminhtml/Index

<?php

namespace Dolphin\AddConditionFiled\Controller\Adminhtml\Index;

class NewActionHtml extends \Dolphin\AddConditionFiled\Controller\Adminhtml\Index\Rule
{
    public function execute()
    {
        $id = $this->getRequest()->getParam('id');
        $typeArr = explode('|', str_replace('-', '/', $this->getRequest()->getParam('type')));
        $type = $typeArr[0];

        $model = $this->_objectManager->create(
            $type
        )->setId(
            $id
        )->setType(
            $type
        )->setRule(
            $this->ruleFactory->create()
        )->setPrefix(
            'actions'
        );
        if (!empty($typeArr[1])) {
            $model->setAttribute($typeArr[1]);
        }

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

Step-8: Create Delete.php at app/code/Dolphin/AddConditionFiled/Controller/Adminhtml/Index

<?php

namespace Dolphin\AddConditionFiled\Controller\Adminhtml\Index;

use Magento\Backend\App\Action;

class Delete extends Action
{
    protected $customConditionModel;

    public function __construct(
        Action\Context $context,
        \Dolphin\AddConditionFiled\Model\CustomConditionFactory $customConditionModel
    ) {
        parent::__construct($context);
        $this->customConditionModel = $customConditionModel;
    }

    public function execute()
    {
        $id = $this->getRequest()->getParam('rule_id');
        $resultRedirect = $this->resultRedirectFactory->create();
        if ($id) {
            try {
                $model = $this->customConditionModel->create();
                $model->load($id);
                $model->delete();
                $this->messageManager->addSuccess(__('The rule is deleted successfully.'));
                return $resultRedirect->setPath('*/*/');
            } catch (\Exception $e) {
                $this->messageManager->addError($e->getMessage());
                return $resultRedirect->setPath('*/*/edit', ['rule_id' => $id]);
            }
        }
        $this->messageManager->addError(__('The rule does not exist'));
        return $resultRedirect->setPath('*/*/');
    }
}

Step-9: Create Save.php at app/code/Dolphin/AddConditionFiled/Controller/Adminhtml/Index

<?php

namespace Dolphin\AddConditionFiled\Controller\Adminhtml\Index;

use Dolphin\AddConditionFiled\Model\CustomConditionFactory;
use Magento\Backend\App\Action;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Framework\Controller\ResultFactory;

class Save extends \Magento\Backend\App\Action
{

    protected $ruledatamodel;
    protected $dataPersistor;
    protected $productCollectionFactory;

    public function __construct(
        Action\Context $context,
        CollectionFactory $productCollectionFactory,
        CustomConditionFactory $ruledatamodel
    ) {
        $this->productCollectionFactory = $productCollectionFactory;
        $this->ruledatamodel = $ruledatamodel;
        parent::__construct($context);
    }

    public function execute()
    {
        $data = $this->getRequest()->getPostValue();
        $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
        if (isset($data['rule']['conditions'])) {
            $data['conditions'] = $data['rule']['conditions'];
        }
        if (isset($data['rule'])) {
            unset($data['rule']);
        }
        try {
            $model = $this->ruledatamodel->create();
            $id = $this->getRequest()->getParam('rule_id');
            if ($id) {
                $model->load($id);
            }
            if (!$model->getId() && $id) {
                $this->messageManager->addErrorMessage(__('This rule is no longer exists.'));
                return $resultRedirect->setPath('addconditionfiled/index/index');
            }
            $model->loadPost($data);
            $model->save();
            $this->messageManager->addSuccess(__('Rule has been successfully saved.'));
            if ($this->getRequest()->getParam('back')) {
                if ($this->getRequest()->getParam('back') == 'add') {
                    return $resultRedirect->setPath('addconditionfiled/index/add');
                } else {
                    return $resultRedirect->setPath(
                        'addconditionfiled/index/edit',
                        [
                            'rule_id' => $model->getId(),
                        ]
                    );
                }
            }
        } catch (\Exception $e) {
            $this->messageManager->addException($e, __('Something went wrong while saving the data.'));
            return $resultRedirect->setPath('addconditionfiled/index/add');
        }
        return $resultRedirect->setPath('addconditionfiled/index/index');
    }
}

Before we save the record, we need to create layout for edit from.

Step-10: Create Edit.php at app/code/Dolphin/AddConditionFiled/Controller/Adminhtml/Index

<?php

namespace Dolphin\AddConditionFiled\Controller\Adminhtml\Index;

class Edit extends \Magento\Backend\App\Action
{
    protected $resultPageFactory;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory
    ) {
        parent::__construct($context);
        $this->resultPageFactory = $resultPageFactory;
    }

    public function execute()
    {
        $resultPage = $this->resultPageFactory->create();
        $resultPage->getConfig()->getTitle()->prepend(__('Edit Rule'));
        return $resultPage;
    }
}

Step-11: Create addconditionfiled_index_edit.xml at app/code/Dolphin/AddConditionFiled/view/adminhtml/layout

<?xml version="1.0"?>

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
    <update handle="styles"/>
    <body>
        <referenceContainer name="content">
            <uiComponent name="custom_condition_form"/>
        </referenceContainer>
    </body>
</page>

we add our from ui component custom_condition_form name here for show from into edit mode. Now your Admin from and grid are ready for CRUD Operation.

Form Edit Mode in magento 2

How to check condition with products in Magento 2?

Now we show how to check our condition with products. There is 2 way to check the product is matched with our condition or not.

Method-1

by using getConditions()->validate()

protected $customConditionModel;
    protected $productFactory;

    public function __construct(
        ....................................................
        \Magento\Catalog\Model\ProductFactory $productFactory,
        \Dolphin\AddConditionFiled\Model\CustomConditionFactory $customConditionModel,
        ....................................................
    ) {
        ....................................................
        $this->productFactory = $productFactory;
        $this->customConditionModel = $customConditionModel;
        ....................................................
    }

    public function checkCondition()
    {
        echo "<pre>";
        $prdId = 6; //bag product id
        // Get product data by id
        $prdData = $this->productFactory->create()->load($prdId);
        // get rule collection
        $ruleColl = $this->customConditionModel->create()->getCollection();
        foreach ($ruleColl as $ruleKey => $ruleVal) {
            // check Product with condition
            if ($ruleVal->getConditions()->validate($prdData)) {
                echo "Rule Id " . $ruleVal->getId() . " Match<br/>";
            }
        }
    }

Method-2

by using the Model function getMatchProductIds() which we already created.

protected $customConditionModel;

  public function __construct(
      ....................................................
      \Dolphin\AddConditionFiled\Model\CustomConditionFactory $customConditionModel,
      ....................................................
  ) {
      ....................................................
      $this->customConditionModel = $customConditionModel;
      ....................................................

  }

  public function checkCondition()
  {
      echo "<pre>";
      // get rule collection
      $ruleColl = $this->customConditionModel->create()->getCollection();
      foreach ($ruleColl as $ruleKey => $ruleVal) {
          // get all product's Ids with match with rule
          echo "***** Rule Id " . $ruleVal->getId() . " Match Product Ids ***** <br/>";
          $matchIds = array_values(array_unique($ruleVal->getMatchProductIds()));
          print_r($matchIds);
      }
  }

Now you can create a condition, perform CRUD operation and also understand how to get match product ids or check the product is match a condition or not.

If you want to use Catalog Price Rule then use \Magento\CatalogRule\Model\Rule\Condition\CombineFactory , If you want to use Cart Price Rules then use \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory. After adding class Just add it into the below function at app/code/Dolphin/AddConditionFiled/Model/CustomCondition.php

...............................................................
    ...............................................................

    protected $condCombineFactory;
    protected $condProdCombineF;

    public function __construct(
        ...............................................................
        \Magento\CatalogRule\Model\Rule\Condition\CombineFactory $condCombineFactory,
        \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF,
        ...............................................................
    ) {
        ...............................................................
        $this->condCombineFactory = $condCombineFactory;
        $this->condProdCombineF = $condProdCombineF;
        ...............................................................
    }

    ...............................................................
    ...............................................................

    public function getConditionsInstance()
    {
        return $this->condCombineFactory->create();
    }

    public function getActionsInstance()
    {
        return $this->condCombineFactory->create();
    }

    ...............................................................
    ...............................................................

I hope this helps you. For any doubts regarding this topic, please write your doubts in the comments section.

Mahesh Makwana

Author

We can help you with

  • Dedicated Team
  • Setup Extended Team
  • Product Development
  • Custom App Development

Schedule a Developer Interview And Get 7 Days Risk-Free Trial

Fill out This Form and one of Our Technical Experts will Contact you Within 12 Hours.

    Google
    |

    4.8

    Google
    |

    4.8

    Google
    |

    4.9

    Google
    |

    4.8

    Google
    |

    4.9

    Copyright © 2024 DOLPHIN WEB SOLUTION. All rights reserved.

    TO TOP