SPECIAL OFFER: ENJOY 3 MONTHS OF SHOPIFY FOR $1/MONTH SPECIAL OFFER: ENJOY 3 MONTHS OF SHOPIFY FOR $1/MONTH SPECIAL OFFER: ENJOY 3 MONTHS OF SHOPIFY FOR $1/MONTH SPECIAL OFFER: ENJOY 3 MONTHS OF SHOPIFY FOR $1/MONTH SPECIAL OFFER: ENJOY 3 MONTHS OF SHOPIFY FOR $1/MONTH SPECIAL OFFER: ENJOY 3 MONTHS OF SHOPIFY FOR $1/MONTH SPECIAL OFFER: ENJOY 3 MONTHS OF SHOPIFY FOR $1/MONTH SPECIAL OFFER: ENJOY 3 MONTHS OF SHOPIFY FOR $1/MONTH SPECIAL OFFER: ENJOY 3 MONTHS OF SHOPIFY FOR $1/MONTH SPECIAL OFFER: ENJOY 3 MONTHS OF SHOPIFY FOR $1/MONTH

How create Custom Condition Rules in Magento 2

This article shows you how to create a custom condition rule interface in a block form, not with Magento UI. And notice that I won’t guide you to create a module, you just need to adding the below code into your admin block to make it work so it’s very simple but required knowledge about admin block.

In Magento 2, there are two types of Custom Condition Rules. You can find them in Admin Panel -> Marketing -> Cart Price Rules or Catalog Price Rule -> Conditions tab.

1. SalesRule Condition

These Custom Conditions determine the conditions for the cart. You can use its data to validate the cart is eligible or not.

2. CatalogWidget Condition

These Custom Conditions determine the attributes of the product. You use its data to validate which products match the condition.

3. Let create these two custom condition rules

Create NewConditionHtml.php file in Vendor\Module\Controller\Adminhtml\Rule

This file is required to render new conditions.

<?php

namespace Vendor\Module\Controller\Adminhtml\Rule;

class NewConditionHtml extends \Magento\Backend\App\Action
{
    public function __construct(
        \Magento\Backend\App\Action\Context $context
    ) {
        parent::__construct($context);
    }
    /**
     * New condition html action
     *
     * @return void
     */
    public function execute()
    {
        $id = $this->getRequest()->getParam('id');
        $typeArr = explode('|', str_replace('-', '/', $this->getRequest()->getParam('type')));
        $type = $typeArr[0];
        $form = $this->getRequest()->getParam('form');
        $model = $this->_objectManager->create(
            $type
        )->setId(
            $id
        )->setType(
            $type
        )->setRule(
            $this->_objectManager->get('Magento\SalesRule\Model\Rule') 
        )->setPrefix(
            'conditions'
        );
        if (!empty($typeArr[1])) {
            $model->setAttribute($typeArr[1]);
        }

        if ($model instanceof \Magento\Rule\Model\Condition\AbstractCondition) {
            if (strpos($form, 'conditions_item') !== false) {
                $model->setPrefix('conditions_item');
                $model->setConditions([]);
            }
            $model->setJsFormObject($this->getRequest()->getParam('form'));
            $html = $model->asHtmlRecursive();
        } else {
            $html = '';
        }
        $this->getResponse()->setBody($html);
    }
}

Create SalesRule Condition in Block

protected function _prepareForm()
    { 
        $form = $this->_formFactory->create();
        $form->setHtmlIdPrefix('rule_');
        $fieldset = $form->addFieldset('base_fieldset', []);

        $fieldsetId = 'rule_conditions_fieldset_1';
        $formName = 'condition_rule_form'. uniqid();
        

        /* Getting my model data */
        $model = $this->_coreRegistry->registry('myCustomConditionRuleData');

        /* I saved custom condition data into 'custom_condition' field. Below line is I getting the data.*/
        $Custom_Condition_Parameters = $model->getData('custom_condition');

        /* $this->json is \Magento\Framework\Serialize\Serializer\Json, you need to declare it in __construct() */
        ($Display_Place_Parameters!=NULL)?$Custom_Condition_Parameters = $this->json->unserialize($Custom_Condition_Parameters):NULL;

        $Custom_Condition_Parameters = array('conditions' => $Custom_Condition_Parameters);

        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $modelRule = $objectManager->get('Magento\SalesRule\Model\RuleFactory');
        $modelConditions = $modelRule->create();

        if (is_array($Custom_Condition_Parameters))
        {
            $modelConditions->loadPost($Custom_Condition_Parameters);
            $modelConditions->getConditions()->setJsFormObject($fieldsetId);
        }   
        
        /* 'vendor_module/rule/newConditionHtml' is path of the file created above in admin. */
        $newChildUrl = $this->getUrl(
            'vendor_module/rule/newConditionHtml/form/' . $fieldsetId,
            ['form_namespace' => $fieldsetId]
        );

        $renderer = $this->rendererFieldset->setTemplate('Magento_CatalogRule::promo/fieldset.phtml')
            ->setNewChildUrl($newChildUrl)
            ->setFieldSetId($fieldsetId);
        $fieldset = $form->addFieldset(
            $fieldsetId,
            [
                'legend' => __(
                    'Displaying block if following condition for cart page met (leave blank for alway true).'
                )
            ]
        )->setRenderer(
            $renderer
        );

        $fieldset->addField(
            'custom_conditions',
            'text',
            ['name' => 'custom_conditions', 'label' => __('custom_conditions'), 'title' => __('custom_conditions'), 'data-form-parts' => $formName]
        )->setRule(
            $modelConditions
        )->setRenderer(
            $objectManager->get('Magento\Rule\Block\Conditions')
        );
        
        $form->setValues($model->getData());
        $this->setForm($form);
        return parent::_prepareForm();
}

Create CatalogWidget Condition in Block

protected function _prepareForm()
    { 
        $form = $this->_formFactory->create();
        $form->setHtmlIdPrefix('rule_');
        $fieldset = $form->addFieldset('base_fieldset', []);

        $fieldsetId = 'rule_conditions_fieldset_1';
        $formName = 'condition_rule_form'. uniqid();
        

        /* Getting my model data */
        $model = $this->_coreRegistry->registry('myCustomConditionRuleData');

        /* I saved custom condition data into 'custom_condition' field. Below line is I getting the data.*/
        $Custom_Condition_Parameters = $model->getData('custom_condition');

        /* $this->json is \Magento\Framework\Serialize\Serializer\Json, you need to declare it in __construct() */
        ($Display_Place_Parameters!=NULL)?$Custom_Condition_Parameters = $this->json->unserialize($Custom_Condition_Parameters):NULL;

        $Custom_Condition_Parameters = array('conditions' => $Custom_Condition_Parameters);

        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $modelRule = $objectManager->get('Magento\CatalogWidget\Model\RuleFactory');
        $modelConditions = $modelRule->create();

        if (is_array($Custom_Condition_Parameters))
        {
            $modelConditions->loadPost($Custom_Condition_Parameters);
            $modelConditions->getConditions()->setJsFormObject($fieldsetId);
        }   
        
        /* 'vendor_module/rule/newConditionHtml' is path of the file created above in admin. */
        $newChildUrl = $this->getUrl(
            'vendor_module/rule/newConditionHtml/form/' . $fieldsetId,
            ['form_namespace' => $fieldsetId]
        );

        $renderer = $this->rendererFieldset->setTemplate('Magento_CatalogRule::promo/fieldset.phtml')
            ->setNewChildUrl($newChildUrl)
            ->setFieldSetId($fieldsetId);
        $fieldset = $form->addFieldset(
            $fieldsetId,
            [
                'legend' => __(
                    'Choose the conditions to define what products display block (leave blank for all products).'
                )
            ]
        )->setRenderer(
            $renderer
        );

        $fieldset->addField(
            'custom_conditions',
            'text',
            ['name' => 'custom_conditions', 'label' => __('custom_conditions'), 'title' => __('custom_conditions'), 'data-form-parts' => $formName]
        )->setRule(
            $modelConditions
        )->setRenderer(
            $objectManager->get('Magento\Rule\Block\Conditions')
        );
        
        $form->setValues($model->getData());
        $this->setForm($form);
        return parent::_prepareForm();
}

The only difference between creating SalesRule and CatalogWidget is the line:

$modelRule = $objectManager->get('Magento\CatalogWidget\Model\RuleFactory'); 
$modelRule = $objectManager->get('Magento\SalesRule\Model\RuleFactory');  

And now you have a custom condition rule in your admin block.