{"id":6057,"date":"2016-09-05T15:53:06","date_gmt":"2016-09-05T15:53:06","guid":{"rendered":"https:\/\/blog.mageworx.com\/?p=6057"},"modified":"2022-11-09T10:33:19","modified_gmt":"2022-11-09T10:33:19","slug":"magento-2-module-with-conditions-model-fieldset","status":"publish","type":"post","link":"https:\/\/www.mageworx.com\/blog\/magento-2-module-with-conditions-model-fieldset","title":{"rendered":"The example of Magento 2 Module with Conditions Model and Fieldset (Part 1)"},"content":{"rendered":"\n<!-- SEO Ultimate (http:\/\/www.seodesignsolutions.com\/wordpress-seo\/) - Code Inserter module -->\n<!-- Google Tag Manager (noscript) -->\r\n<noscript><iframe src=\"https:\/\/www.googletagmanager.com\/ns.html?id=GTM-5DTCW7B8\"\r\nheight=\"0\" width=\"0\" style=\"display:none;visibility:hidden\"><\/iframe><\/noscript>\r\n<!-- End Google Tag Manager (noscript) -->\n<!-- \/SEO Ultimate -->\n\n<span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Reading Time: <\/span> <span class=\"rt-time\"> 13<\/span> <span class=\"rt-label rt-postfix\">minutes<\/span><\/span><p>While browsing Magento forums we often bump to the threads where developers are asking how to create an extension with custom rules and fieldset. Hence, we&#8217;ve decided to illustrate that on the example of a sample module that can be also used for further validating and other development purposes.<\/p>\n<p>Let&#8217;s roll in!<\/p>\n<p>To add a conditional field to the default model (and further utilize it for validating purposes), you will need to create a separate model (or modify the existing one) that contains the corresponding fields.<\/p>\n<p>Below, you&#8217;ll find a description of how to add the condition to<em> both the model and interface<\/em> without using Magento UI.<\/p>\n<p>First, let&#8217;s create a new and simple module for that (or make some changes in the module you already have):<!--more--><\/p>\n<p><em>app\/code\/Vendor\/Rules\/registration.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 lang:default decode:true\">    &lt;?php\n    \\Magento\\Framework\\Component\\ComponentRegistrar::register(\n        \\Magento\\Framework\\Component\\ComponentRegistrar::MODULE,\n        'Vendor_Rules',\n        __DIR__\n    );\n    ?&gt;\n<\/pre>\n<p><em>app\/code\/Vendor\/Rules\/composer.json<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 lang:default decode:true\">    {\n        \"name\": \"vendor\/module-rules\",\n        \"description\": \"N\/A\",\n        \"type\": \"magento2-module\",\n        \"version\": \"1.0.0\",\n        \"license\": [\n            \"OSL-3.0\",\n            \"AFL-3.0\"\n        ],\n        \"autoload\": {\n            \"files\": [\n                \"registration.php\"\n            ],\n            \"psr-4\": {\n                \"Vendor\\\\Rules\\\\\": \"\"\n            }\n        }\n    }\n<\/pre>\n<p><em>app\/code\/Vendor\/Rules\/etc\/module.xml<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 lang:default decode:true\">    &lt;?xml version=\"1.0\"?&gt;\n    &lt;config xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:Module\/etc\/module.xsd\"&gt;\n        &lt;module name=\"Vendor_Rules\" setup_version=\"1.0.0\"&gt;\n        &lt;\/module&gt;\n    &lt;\/config&gt;\n<\/pre>\n<p>These files declare the <em>Rules<\/em> module in the <em>Vendor<\/em> namespace.<\/p>\n<p>Next, let&#8217;s add the files responsible for the main configuration setup:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/etc\/acl.xml<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 lang:default decode:true\">    &lt;?xml version=\"1.0\"?&gt;\n    &lt;config xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:Acl\/etc\/acl.xsd\"&gt;\n        &lt;acl&gt;\n            &lt;resources&gt;\n                &lt;resource id=\"Magento_Backend::admin\"&gt;\n                    &lt;resource id=\"Magento_Backend::marketing\"&gt;\n                        &lt;resource id=\"Magento_CatalogRule::promo\"&gt;\n                            &lt;resource id=\"Vendor_Rules::rules\" sortOrder=\"40\" title=\"Example Rules\" \/&gt;\n                        &lt;\/resource&gt;\n                    &lt;\/resource&gt;\n                &lt;\/resource&gt;\n            &lt;\/resources&gt;\n        &lt;\/acl&gt;\n    &lt;\/config&gt;<\/pre>\n<p>Note, we&#8217;ve added <strong>acl<\/strong> in order to disable the module for certain administrators.<\/p>\n<p><em>app\/code\/Vendor\/Rules\/etc\/adminhtml\/routes.xml<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?xml version=\"1.0\"?&gt;\n&lt;config xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:App\/etc\/routes.xsd\"&gt;\n    &lt;router id=\"admin\"&gt;\n        &lt;route id=\"vendor_rules\" frontName=\"vendor_rules\"&gt;\n            &lt;module name=\"Vendor_Rules\" before=\"Magento_Backend\" \/&gt;\n        &lt;\/route&gt;\n    &lt;\/router&gt;\n&lt;\/config&gt;<\/pre>\n<p>Also, we&#8217;ve added an admin route with the `<em>vendor_rules<\/em>` name and id. Later, we can use it to get an access to the modules&#8217; interface in the admin panel.<\/p>\n<p><em>app\/code\/Vendor\/Rules\/etc\/adminhtml\/menu.xml<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true \">&lt;?xml version=\"1.0\"?&gt;\n&lt;config xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:module:Magento_Backend:etc\/menu.xsd\"&gt;\n    &lt;menu&gt;\n        &lt;add id=\"Vendor_Rules::vendor_rules\"\n             title=\"Example Rules\"\n             module=\"Vendor_Rules\"\n             parent=\"Magento_CatalogRule::promo\"\n             sortOrder=\"40\"\n             action=\"vendor_rules\/example_rule\/index\"\n             dependsOnModule=\"Magento_Sales\"\n             resource=\"Vendor_Rules::rule\"\n        \/&gt;\n    &lt;\/menu&gt;\n&lt;\/config&gt;<\/pre>\n<menu><\/menu>\n<p>By doing that, we&#8217;ve added a menu section for our module in the Marketing tab.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-6062\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/83a5abc9d83d502f5602ec8298121f4e-1024x460.png\" alt=\"\" width=\"1024\" height=\"460\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/83a5abc9d83d502f5602ec8298121f4e-1024x460.png 1024w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/83a5abc9d83d502f5602ec8298121f4e-150x67.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/83a5abc9d83d502f5602ec8298121f4e-300x135.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/83a5abc9d83d502f5602ec8298121f4e-768x345.png 768w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/83a5abc9d83d502f5602ec8298121f4e.png 1863w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>Now, let&#8217;s add the tables to the module database. These fields are default, and you can expand them whenever needed.<\/p>\n<p>Let&#8217;s name the table according to the module name &#8211; `<em>vendor_rules<\/em>`.<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Setup\/InstallSchema.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Setup;\n\nuse Magento\\Framework\\DB\\Ddl\\Table;\nuse Magento\\Framework\\Setup\\InstallSchemaInterface;\nuse Magento\\Framework\\Setup\\ModuleContextInterface;\nuse Magento\\Framework\\Setup\\SchemaSetupInterface;\n\nclass InstallSchema implements InstallSchemaInterface\n{\n\n    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)\n    {\n        $installer = $setup;\n        $installer-&gt;startSetup();\n\n        $table = $installer-&gt;getConnection()-&gt;newTable(\n            $installer-&gt;getTable('vendor_rules')\n        )-&gt;addColumn(\n            'rule_id',\n            Table::TYPE_INTEGER,\n            null,\n            ['identity' =&gt; true, 'unsigned' =&gt; true, 'nullable' =&gt; false, 'primary' =&gt; true],\n            'Rule Id'\n        )-&gt;addColumn(\n            'name',\n            Table::TYPE_TEXT,\n            255,\n            [],\n            'Name'\n        )-&gt;addColumn(\n            'description',\n            Table::TYPE_TEXT,\n            '64k',\n            [],\n            'Description'\n        )-&gt;addColumn(\n            'from_date',\n            Table::TYPE_DATE,\n            null,\n            ['nullable' =&gt; true, 'default' =&gt; null],\n            'From'\n        )-&gt;addColumn(\n            'to_date',\n            Table::TYPE_DATE,\n            null,\n            ['nullable' =&gt; true, 'default' =&gt; null],\n            'To'\n        )-&gt;addColumn(\n            'is_active',\n            Table::TYPE_SMALLINT,\n            null,\n            ['nullable' =&gt; false, 'default' =&gt; '0'],\n            'Is Active'\n        )-&gt;addColumn(\n            'conditions_serialized',\n            Table::TYPE_TEXT,\n            '2M',\n            [],\n            'Conditions Serialized'\n        )-&gt;addColumn(\n            'sort_order',\n            Table::TYPE_INTEGER,\n            null,\n            ['unsigned' =&gt; true, 'nullable' =&gt; false, 'default' =&gt; '0'],\n            'Sort Order (Priority)'\n        )-&gt;addIndex(\n            $installer-&gt;getIdxName('vendor_rules', ['sort_order', 'is_active', 'to_date', 'from_date']),\n            ['sort_order', 'is_active', 'to_date', 'from_date']\n        )-&gt;setComment(\n            'Own Rules'\n        );\n\n        $installer-&gt;getConnection()-&gt;createTable($table);\n        $installer-&gt;endSetup();\n    }\n}<\/pre>\n<p>Our conditions will be stored in the `<em>conditions_serialized<\/em>` field. The rest of the data just describes the model (example).<\/p>\n<p>Also, don&#8217;t forget to add the module uninstall file! That is done to delete the table after installing it via `<em>Composer<\/em>` and\/or deleting.<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Setup\/Uninstall.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Setup;\n\nuse Magento\\Framework\\Setup\\UninstallInterface;\nuse Magento\\Framework\\Setup\\SchemaSetupInterface;\nuse Magento\\Framework\\Setup\\ModuleContextInterface;\n\nclass Uninstall implements UninstallInterface\n{\n    \/**\n     * Module uninstall code\n     *\n     * @param SchemaSetupInterface $setup\n     * @param ModuleContextInterface $context\n     * @return void\n     *\/\n    public function uninstall(\n        SchemaSetupInterface $setup,\n        ModuleContextInterface $context\n    ) {\n        $setup-&gt;startSetup();\n\n        $connection = $setup-&gt;getConnection();\n\n        $connection-&gt;dropTable($connection-&gt;getTableName('vendor_rules'));\n\n        $setup-&gt;endSetup();\n    }\n}<\/pre>\n<p>Now, we have a table with the model description and we need to complete the model itself, and include into it the appropriate resource model and collection.<\/p>\n<p>The model will be called &#8216;<em>Rule<\/em>&#8216;:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Model\/Rule.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Model;\n\nuse Magento\\Quote\\Model\\Quote\\Address;\nuse Magento\\Rule\\Model\\AbstractModel;\n\n\/**\n * Class Rule\n * @package Vendor\\Rules\\Model\n *\n * @method int|null getRuleId()\n * @method Rule setRuleId(int $id)\n *\/\nclass Rule extends AbstractModel\n{\n    \/**\n     * Prefix of model events names\n     *\n     * @var string\n     *\/\n    protected $_eventPrefix = 'vendor_rules';\n\n    \/**\n     * Parameter name in event\n     *\n     * In observe method you can use $observer-&gt;getEvent()-&gt;getRule() in this case\n     *\n     * @var string\n     *\/\n    protected $_eventObject = 'rule';\n\n    \/** @var \\Magento\\SalesRule\\Model\\Rule\\Condition\\CombineFactory *\/\n    protected $condCombineFactory;\n\n    \/** @var \\Magento\\SalesRule\\Model\\Rule\\Condition\\Product\\CombineFactory *\/\n    protected $condProdCombineF;\n\n    \/**\n     * Store already validated addresses and validation results\n     *\n     * @var array\n     *\/\n    protected $validatedAddresses = [];\n\n    \/**\n     * @param \\Magento\\Framework\\Model\\Context $context\n     * @param \\Magento\\Framework\\Registry $registry\n     * @param \\Magento\\Framework\\Data\\FormFactory $formFactory\n     * @param \\Magento\\Framework\\Stdlib\\DateTime\\TimezoneInterface $localeDate\n     * @param \\Magento\\SalesRule\\Model\\Rule\\Condition\\CombineFactory $condCombineFactory\n     * @param \\Magento\\SalesRule\\Model\\Rule\\Condition\\Product\\CombineFactory $condProdCombineF\n     * @param \\Magento\\Framework\\Model\\ResourceModel\\AbstractResource $resource\n     * @param \\Magento\\Framework\\Data\\Collection\\AbstractDb $resourceCollection\n     * @param array $data\n     * @SuppressWarnings(PHPMD.ExcessiveParameterList)\n     *\/\n    public function __construct(\n        \\Magento\\Framework\\Model\\Context $context,\n        \\Magento\\Framework\\Registry $registry,\n        \\Magento\\Framework\\Data\\FormFactory $formFactory,\n        \\Magento\\Framework\\Stdlib\\DateTime\\TimezoneInterface $localeDate,\n        \\Magento\\SalesRule\\Model\\Rule\\Condition\\CombineFactory $condCombineFactory,\n        \\Magento\\SalesRule\\Model\\Rule\\Condition\\Product\\CombineFactory $condProdCombineF,\n        \\Magento\\Framework\\Model\\ResourceModel\\AbstractResource $resource = null,\n        \\Magento\\Framework\\Data\\Collection\\AbstractDb $resourceCollection = null,\n        array $data = []\n    ) {\n        $this-&gt;condCombineFactory = $condCombineFactory;\n        $this-&gt;condProdCombineF = $condProdCombineF;\n        parent::__construct($context, $registry, $formFactory, $localeDate, $resource, $resourceCollection, $data);\n    }\n\n    \/**\n     * Set resource model and Id field name\n     *\n     * @return void\n     *\/\n    protected function _construct()\n    {\n        parent::_construct();\n        $this-&gt;_init('Vendor\\Rules\\Model\\ResourceModel\\Rule');\n        $this-&gt;setIdFieldName('rule_id');\n    }\n\n    \/**\n     * Get rule condition combine model instance\n     *\n     * @return \\Magento\\SalesRule\\Model\\Rule\\Condition\\Combine\n     *\/\n    public function getConditionsInstance()\n    {\n        return $this-&gt;condCombineFactory-&gt;create();\n    }\n\n    \/**\n     * Get rule condition product combine model instance\n     *\n     * @return \\Magento\\SalesRule\\Model\\Rule\\Condition\\Product\\Combine\n     *\/\n    public function getActionsInstance()\n    {\n        return $this-&gt;condProdCombineF-&gt;create();\n    }\n\n    \/**\n     * Check cached validation result for specific address\n     *\n     * @param Address $address\n     * @return bool\n     *\/\n    public function hasIsValidForAddress($address)\n    {\n        $addressId = $this-&gt;_getAddressId($address);\n        return isset($this-&gt;validatedAddresses[$addressId]) ? true : false;\n    }\n\n    \/**\n     * Set validation result for specific address to results cache\n     *\n     * @param Address $address\n     * @param bool $validationResult\n     * @return $this\n     *\/\n    public function setIsValidForAddress($address, $validationResult)\n    {\n        $addressId = $this-&gt;_getAddressId($address);\n        $this-&gt;validatedAddresses[$addressId] = $validationResult;\n        return $this;\n    }\n\n    \/**\n     * Get cached validation result for specific address\n     *\n     * @param Address $address\n     * @return bool\n     * @SuppressWarnings(PHPMD.BooleanGetMethodName)\n     *\/\n    public function getIsValidForAddress($address)\n    {\n        $addressId = $this-&gt;_getAddressId($address);\n        return isset($this-&gt;validatedAddresses[$addressId]) ? $this-&gt;validatedAddresses[$addressId] : false;\n    }\n\n    \/**\n     * Return id for address\n     *\n     * @param Address $address\n     * @return string\n     *\/\n    private function _getAddressId($address)\n    {\n        if ($address instanceof Address) {\n            return $address-&gt;getId();\n        }\n        return $address;\n    }\n}<\/pre>\n<p>As you can see, our model inherits from the `<em>Magento\\Rule\\Model\\AbstractModel<\/em>` model that already has all the required methods.<\/p>\n<p>Right in the Constructor, we&#8217;ll add condition factories that allow us to work with them and create multiple methods. This should give us the understanding of how the model works.<\/p>\n<p>Note that we are using the default condition models from the Magento <strong>SalesRule<\/strong> (`<em>\\Magento\\SalesRule\\Model\\Rule\\Condition<\/em>`) module. If you need to expand the conditions, you can add your own classes and\/or rewrite them completely or inherit from the base available classes. In can be useful when you want to add a special condition that is not included in the default conditions. For example, **<em>Subtotal With Discount<\/em>**.<\/p>\n<p>Now, it&#8217;s time to add a resource model from the Constructor:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Model\/ResourceModel\/Rule.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Model\\ResourceModel;\n\nclass Rule extends \\Magento\\Rule\\Model\\ResourceModel\\AbstractResource\n{\n\n    \/**\n     * Initialize main table and table id field\n     *\n     * @return void\n     *\/\n    protected function _construct()\n    {\n        $this-&gt;_init('vendor_rules', 'rule_id');\n    }\n}<\/pre>\n<p>And a collection:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Model\/ResourceModel\/Rule\/Collection.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Model\\ResourceModel\\Rule;\n\nclass Collection extends \\Magento\\Rule\\Model\\ResourceModel\\Rule\\Collection\\AbstractCollection\n{\n    \/**\n     * @var \\Magento\\Framework\\Stdlib\\DateTime\\TimezoneInterface\n     *\/\n    protected $date;\n\n    \/**\n     * @param \\Magento\\Framework\\Data\\Collection\\EntityFactory $entityFactory\n     * @param \\Psr\\Log\\LoggerInterface $logger\n     * @param \\Magento\\Framework\\Data\\Collection\\Db\\FetchStrategyInterface $fetchStrategy\n     * @param \\Magento\\Framework\\Event\\ManagerInterface $eventManager\n     * @param \\Magento\\Framework\\Stdlib\\DateTime\\TimezoneInterface $date\n     * @param mixed $connection\n     * @param \\Magento\\Framework\\Model\\ResourceModel\\Db\\AbstractDb $resource\n     *\/\n    public function __construct(\n        \\Magento\\Framework\\Data\\Collection\\EntityFactory $entityFactory,\n        \\Psr\\Log\\LoggerInterface $logger,\n        \\Magento\\Framework\\Data\\Collection\\Db\\FetchStrategyInterface $fetchStrategy,\n        \\Magento\\Framework\\Event\\ManagerInterface $eventManager,\n        \\Magento\\Framework\\Stdlib\\DateTime\\TimezoneInterface $date,\n        \\Magento\\Framework\\DB\\Adapter\\AdapterInterface $connection = null,\n        \\Magento\\Framework\\Model\\ResourceModel\\Db\\AbstractDb $resource = null\n    ) {\n        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);\n        $this-&gt;date = $date;\n    }\n\n    \/**\n     * Set resource model and determine field mapping\n     *\n     * @return void\n     *\/\n    protected function _construct()\n    {\n        $this-&gt;_init('Vendor\\Rules\\Model\\Rule', 'Vendor\\Rules\\Model\\ResourceModel\\Rule');\n    }\n\n    \/**\n     * Filter collection by specified date.\n     * Filter collection to only active rules.\n     *\n     * @param string|null $now\n     * @use $this-&gt;addStoreGroupDateFilter()\n     * @return $this\n     *\/\n    public function setValidationFilter($now = null)\n    {\n        if (!$this-&gt;getFlag('validation_filter')) {\n            $this-&gt;addDateFilter($now);\n            $this-&gt;addIsActiveFilter();\n            $this-&gt;setOrder('sort_order', self::SORT_ORDER_DESC);\n            $this-&gt;setFlag('validation_filter', true);\n        }\n\n        return $this;\n    }\n\n    \/**\n     * From date or to date filter\n     *\n     * @param $now\n     * @return $this\n     *\/\n    public function addDateFilter($now)\n    {\n        $this-&gt;getSelect()-&gt;where(\n            'from_date is null or from_date &lt;= ?',\n            $now\n        )-&gt;where(\n            'to_date is null or to_date &gt;= ?',\n            $now\n        );\n\n        return $this;\n    }\n}<\/pre>\n<p>There are also some collection filter methods that can help you cut off the inactive or mismatching the current date rules while validating. For example, these will help us decrease server overloads: `<em>setValidationFilter<\/em>` \u0438 `<em>addDateFilter<\/em>`.<\/p>\n<p>Now, we&#8217;ve finished with the structure declaration and are halfway through with this task!<\/p>\n<p>Next, let&#8217;s switch to the interface in the admin panel. We need the Controller with a set of actions (such as <em>Save, Add, Edit, Grid Display, Conditions reload<\/em>) and a layout with blocks.<\/p>\n<p>Let&#8217;s start with the Controller itself. First, declare the common Controller:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Controller\/Adminhtml\/Example\/Rule.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Controller\\Adminhtml\\Example;\n\nabstract class Rule extends \\Magento\\Backend\\App\\Action\n{\n    \/**\n     * Core registry\n     *\n     * @var \\Magento\\Framework\\Registry\n     *\/\n    protected $coreRegistry = null;\n\n    \/**\n     * @var \\Magento\\Framework\\App\\Response\\Http\\FileFactory\n     *\/\n    protected $fileFactory;\n\n    \/**\n     * @var \\Magento\\Framework\\Stdlib\\DateTime\\Filter\\Date\n     *\/\n    protected $dateFilter;\n\n    \/**\n     * @var \\Vendor\\Rules\\Model\\RuleFactory\n     *\/\n    protected $ruleFactory;\n\n    \/**\n     * @var \\Psr\\Log\\LoggerInterface\n     *\/\n    protected $logger;\n\n    \/**\n     * @param \\Magento\\Backend\\App\\Action\\Context $context\n     * @param \\Magento\\Framework\\Registry $coreRegistry\n     * @param \\Magento\\Framework\\App\\Response\\Http\\FileFactory $fileFactory\n     * @param \\Magento\\Framework\\Stdlib\\DateTime\\Filter\\Date $dateFilter\n     * @param \\Vendor\\Rules\\Model\\RuleFactory $ruleFactory\n     * @param \\Psr\\Log\\LoggerInterface $logger\n     *\/\n    public function __construct(\n        \\Magento\\Backend\\App\\Action\\Context $context,\n        \\Magento\\Framework\\Registry $coreRegistry,\n        \\Magento\\Framework\\App\\Response\\Http\\FileFactory $fileFactory,\n        \\Magento\\Framework\\Stdlib\\DateTime\\Filter\\Date $dateFilter,\n        \\Vendor\\Rules\\Model\\RuleFactory $ruleFactory,\n        \\Psr\\Log\\LoggerInterface $logger\n    ) {\n        parent::__construct($context);\n        $this-&gt;coreRegistry = $coreRegistry;\n        $this-&gt;fileFactory = $fileFactory;\n        $this-&gt;dateFilter = $dateFilter;\n        $this-&gt;ruleFactory = $ruleFactory;\n        $this-&gt;logger = $logger;\n    }\n\n    \/**\n     * Initiate rule\n     *\n     * @return void\n     *\/\n    protected function _initRule()\n    {\n        $rule = $this-&gt;ruleFactory-&gt;create();\n        $this-&gt;coreRegistry-&gt;register(\n            'current_rule',\n            $rule\n        );\n        $id = (int)$this-&gt;getRequest()-&gt;getParam('id');\n\n        if (!$id &amp;&amp; $this-&gt;getRequest()-&gt;getParam('rule_id')) {\n            $id = (int)$this-&gt;getRequest()-&gt;getParam('rule_id');\n        }\n\n        if ($id) {\n            $this-&gt;coreRegistry-&gt;registry('current_rule')-&gt;load($id);\n        }\n    }\n\n    \/**\n     * Initiate action\n     *\n     * @return Rule\n     *\/\n    protected function _initAction()\n    {\n        $this-&gt;_view-&gt;loadLayout();\n        $this-&gt;_setActiveMenu('Vendor_Rules::vendor_rules')\n            -&gt;_addBreadcrumb(__('Example Rules'), __('Example Rules'));\n        return $this;\n    }\n\n    \/**\n     * Returns result of current user permission check on resource and privilege\n     *\n     * @return bool\n     *\/\n    protected function _isAllowed()\n    {\n        return $this-&gt;_authorization-&gt;isAllowed('Vendor_Rules::rules');\n    }\n}<\/pre>\n<p>Here, we need to call out our models&#8217; factory in the Constructor. That is done to make them (and some auxiliary classes, like a register and a logger) publicly available.<\/p>\n<p>The `<strong>_initRule<\/strong>` method is responsible for the current rule initialization or creating of a new and empty one with the ability of adding it to the register.<br \/>\nThe `<strong>_initAction()<\/strong>` method loads a layout and makes the modules&#8217; menu available for actions (also, it adds breadcumbs).<br \/>\nThe `<strong>_isAllowed()<\/strong>` method checks if the current admin has an access to the Controller.<\/p>\n<p>At the next step, we are going to add the default actions:<\/p>\n<ul>\n<li><em>Deleting:<\/em><\/li>\n<\/ul>\n<p><em>app\/code\/Vendor\/Rules\/Controller\/Adminhtml\/Example\/Rule\/Delete.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule;\n\nclass Delete extends \\Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule\n{\n    \/**\n     * Delete rule action\n     *\n     * @return void\n     *\/\n    public function execute()\n    {\n        $id = $this-&gt;getRequest()-&gt;getParam('id');\n        if ($id) {\n            try {\n                \/** @var \\Vendor\\Rules\\Model\\Rule $model *\/\n                $model = $this-&gt;ruleFactory-&gt;create();\n                $model-&gt;load($id);\n                $model-&gt;delete();\n                $this-&gt;messageManager-&gt;addSuccessMessage(__('You deleted the rule.'));\n                $this-&gt;_redirect('vendor_rules\/*\/');\n                return;\n            } catch (\\Magento\\Framework\\Exception\\LocalizedException $e) {\n                $this-&gt;messageManager-&gt;addErrorMessage($e-&gt;getMessage());\n            } catch (\\Exception $e) {\n                $this-&gt;messageManager-&gt;addErrorMessage(\n                    __('We can\\'t delete the rule right now. Please review the log and try again.')\n                );\n                $this-&gt;logger-&gt;critical($e);\n                $this-&gt;_redirect('vendor_rules\/*\/edit', ['id' =&gt; $this-&gt;getRequest()-&gt;getParam('id')]);\n                return;\n            }\n        }\n        $this-&gt;messageManager-&gt;addErrorMessage(__('We can\\'t find a rule to delete.'));\n        $this-&gt;_redirect('vendor_rules\/*\/');\n    }\n}<\/pre>\n<ul>\n<li><em>Adding<\/em> (NOTE! Do not use the `New` word because it is keyword in the PHP):<\/li>\n<\/ul>\n<p><em><br \/>\napp\/code\/Vendor\/Rules\/Controller\/Adminhtml\/Example\/Rule\/NewAction.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule;\n\nclass NewAction extends \\Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule\n{\n    \/**\n     * New action\n     *\n     * @return void\n     *\/\n    public function execute()\n    {\n        $this-&gt;_forward('edit');\n    }\n}<\/pre>\n<ul>\n<li><em>Editing<\/em><\/li>\n<\/ul>\n<p><em>app\/code\/Vendor\/Rules\/Controller\/Adminhtml\/Example\/Rule\/Edit.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule;\n\nclass Edit extends \\Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule\n{\n    \/**\n     * Rule edit action\n     *\n     * @return void\n     *\/\n    public function execute()\n    {\n        $id = $this-&gt;getRequest()-&gt;getParam('id');\n        \/** @var \\Vendor\\Rules\\Model\\Rule $model *\/\n        $model = $this-&gt;ruleFactory-&gt;create();\n\n        if ($id) {\n            $model-&gt;load($id);\n            if (!$model-&gt;getRuleId()) {\n                $this-&gt;messageManager-&gt;addErrorMessage(__('This rule no longer exists.'));\n                $this-&gt;_redirect('vendor_rules\/*');\n                return;\n            }\n        }\n\n        \/\/ set entered data if was error when we do save\n        $data = $this-&gt;_session-&gt;getPageData(true);\n        if (!empty($data)) {\n            $model-&gt;addData($data);\n        }\n\n        $model-&gt;getConditions()-&gt;setJsFormObject('rule_conditions_fieldset');\n\n        $this-&gt;coreRegistry-&gt;register('current_rule', $model);\n\n        $this-&gt;_initAction();\n        $this-&gt;_view-&gt;getLayout()\n            -&gt;getBlock('example_rule_edit')\n            -&gt;setData('action', $this-&gt;getUrl('vendor_rules\/*\/save'));\n\n        $this-&gt;_addBreadcrumb($id ? __('Edit Rule') : __('New Rule'), $id ? __('Edit Rule') : __('New Rule'));\n\n        $this-&gt;_view-&gt;getPage()-&gt;getConfig()-&gt;getTitle()-&gt;prepend(\n            $model-&gt;getRuleId() ? $model-&gt;getName() : __('New Rule')\n        );\n        $this-&gt;_view-&gt;renderLayout();\n    }\n}<\/pre>\n<ul>\n<li><em>Saving<\/em><\/li>\n<\/ul>\n<p><em>app\/code\/Vendor\/Rules\/Controller\/Adminhtml\/Example\/Rule\/Save.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule;\n\nclass Save extends \\Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule\n{\n\n    \/**\n     * @param \\Magento\\Backend\\App\\Action\\Context $context\n     * @param \\Magento\\Framework\\Registry $coreRegistry\n     * @param \\Magento\\Framework\\App\\Response\\Http\\FileFactory $fileFactory\n     * @param \\Magento\\Framework\\Stdlib\\DateTime\\Filter\\Date $dateFilter\n     * @param \\Vendor\\Rules\\Model\\RuleFactory $ruleFactory\n     * @param \\Psr\\Log\\LoggerInterface $logger\n     *\/\n    public function __construct(\n        \\Magento\\Backend\\App\\Action\\Context $context,\n        \\Magento\\Framework\\Registry $coreRegistry,\n        \\Magento\\Framework\\App\\Response\\Http\\FileFactory $fileFactory,\n        \\Magento\\Framework\\Stdlib\\DateTime\\Filter\\Date $dateFilter,\n        \\Vendor\\Rules\\Model\\RuleFactory $ruleFactory,\n        \\Psr\\Log\\LoggerInterface $logger\n    ) {\n\n        parent::__construct($context, $coreRegistry, $fileFactory, $dateFilter, $ruleFactory, $logger);\n    }\n\n    \/**\n     * Rule save action\n     *\n     * @return void\n     *\/\n    public function execute()\n    {\n        if (!$this-&gt;getRequest()-&gt;getPostValue()) {\n            $this-&gt;_redirect('vendor_rules\/*\/');\n        }\n\n        try {\n            \/** @var $model \\Vendor\\Rules\\Model\\Rule *\/\n            $model = $this-&gt;ruleFactory-&gt;create();\n            $this-&gt;_eventManager-&gt;dispatch(\n                'adminhtml_controller_vendor_rules_prepare_save',\n                ['request' =&gt; $this-&gt;getRequest()]\n            );\n            $data = $this-&gt;getRequest()-&gt;getPostValue();\n            $inputFilter = new \\Zend_Filter_Input(\n                ['from_date' =&gt; $this-&gt;dateFilter, 'to_date' =&gt; $this-&gt;dateFilter],\n                [],\n                $data\n            );\n            $data = $inputFilter-&gt;getUnescaped();\n            $id = $this-&gt;getRequest()-&gt;getParam('rule_id');\n            if ($id) {\n                $model-&gt;load($id);\n            }\n\n            $validateResult = $model-&gt;validateData(new \\Magento\\Framework\\DataObject($data));\n            if ($validateResult !== true) {\n                foreach ($validateResult as $errorMessage) {\n                    $this-&gt;messageManager-&gt;addErrorMessage($errorMessage);\n                }\n                $this-&gt;_session-&gt;setPageData($data);\n                $this-&gt;_redirect('vendor_rules\/*\/edit', ['id' =&gt; $model-&gt;getId()]);\n                return;\n            }\n\n            $data = $this-&gt;prepareData($data);\n            $model-&gt;loadPost($data);\n\n            $this-&gt;_session-&gt;setPageData($model-&gt;getData());\n\n            $model-&gt;save();\n            $this-&gt;messageManager-&gt;addSuccessMessage(__('You saved the rule.'));\n            $this-&gt;_session-&gt;setPageData(false);\n            if ($this-&gt;getRequest()-&gt;getParam('back')) {\n                $this-&gt;_redirect('vendor_rules\/*\/edit', ['id' =&gt; $model-&gt;getId()]);\n                return;\n            }\n            $this-&gt;_redirect('vendor_rules\/*\/');\n            return;\n        } catch (\\Magento\\Framework\\Exception\\LocalizedException $e) {\n            $this-&gt;messageManager-&gt;addErrorMessage($e-&gt;getMessage());\n            $id = (int)$this-&gt;getRequest()-&gt;getParam('rule_id');\n            if (!empty($id)) {\n                $this-&gt;_redirect('vendor_rules\/*\/edit', ['id' =&gt; $id]);\n            } else {\n                $this-&gt;_redirect('vendor_rules\/*\/new');\n            }\n            return;\n        } catch (\\Exception $e) {\n            $this-&gt;messageManager-&gt;addErrorMessage(\n                __('Something went wrong while saving the rule data. Please review the error log.')\n            );\n            $this-&gt;logger-&gt;critical($e);\n            $data = !empty($data) ? $data : [];\n            $this-&gt;_session-&gt;setPageData($data);\n            $this-&gt;_redirect('vendor_rules\/*\/edit', ['id' =&gt; $this-&gt;getRequest()-&gt;getParam('rule_id')]);\n            return;\n        }\n    }\n\n    \/**\n     * Prepares specific data\n     *\n     * @param array $data\n     * @return array\n     *\/\n    protected function prepareData($data)\n    {\n\n        if (isset($data['rule']['conditions'])) {\n            $data['conditions'] = $data['rule']['conditions'];\n        }\n\n        unset($data['rule']);\n\n        return $data;\n    }\n}<\/pre>\n<p>In this case, you should pay attention to the field where the conditions come. The `<em>prepareData<\/em>` method allows us to correctly tranfer conditons to the model before saving. This is how to add new conditions:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Controller\/Adminhtml\/Example\/Rule\/NewConditionHtml.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule;\n\nclass NewConditionHtml extends \\Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule\n{\n    \/**\n     * New condition html action\n     *\n     * @return void\n     *\/\n    public function execute()\n    {\n        $id = $this-&gt;getRequest()-&gt;getParam('id');\n        $typeArr = explode('|', str_replace('-', '\/', $this-&gt;getRequest()-&gt;getParam('type')));\n        $type = $typeArr[0];\n\n        $model = $this-&gt;_objectManager-&gt;create(\n            $type\n        )-&gt;setId(\n            $id\n        )-&gt;setType(\n            $type\n        )-&gt;setRule(\n            $this-&gt;ruleFactory-&gt;create()\n        )-&gt;setPrefix(\n            'conditions'\n        );\n        if (!empty($typeArr[1])) {\n            $model-&gt;setAttribute($typeArr[1]);\n        }\n\n        if ($model instanceof \\Magento\\Rule\\Model\\Condition\\AbstractCondition) {\n            $model-&gt;setJsFormObject($this-&gt;getRequest()-&gt;getParam('form'));\n            $html = $model-&gt;asHtmlRecursive();\n        } else {\n            $html = '';\n        }\n        $this-&gt;getResponse()-&gt;setBody($html);\n    }\n}<\/pre>\n<p>This class is responsible for loading the conditions that have been chosen in the interface (all the conditions can&#8217;t be loaded at once).<\/p>\n<ul>\n<li>And the last one is <em>Grid<\/em>:<\/li>\n<\/ul>\n<p><em>app\/code\/Vendor\/Rules\/Controller\/Adminhtml\/Example\/Rule\/Index.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule;\n\nclass Index extends \\Vendor\\Rules\\Controller\\Adminhtml\\Example\\Rule\n{\n    \/**\n     * Index action\n     *\n     * @return void\n     *\/\n    public function execute()\n    {\n        $this-&gt;_initAction()-&gt;_addBreadcrumb(__('Example Rules'), __('Example Rules'));\n        $this-&gt;_view-&gt;getPage()-&gt;getConfig()-&gt;getTitle()-&gt;prepend(__('Example Rules'));\n        $this-&gt;_view-&gt;renderLayout('root');\n    }\n}<\/pre>\n<p>Next, we need to create all the required blocks and layout. First, let&#8217;s add a container for the Grid:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Block\/Adminhtml\/Example\/Rule.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Block\\Adminhtml\\Example;\n\nclass Rule extends \\Magento\\Backend\\Block\\Widget\\Grid\\Container\n{\n    \/**\n     * Constructor\n     *\n     * @return void\n     *\/\n    protected function _construct()\n    {\n        $this-&gt;_controller = 'example_rule';\n        $this-&gt;_headerText = __('Example Rules');\n        $this-&gt;_addButtonLabel = __('Add New Rule');\n        parent::_construct();\n    }\n}<\/pre>\n<p>Note that when doing this, you&#8217;ll be able to add only the Controller&#8217;s name (it will be used when forming Grid and Lable). In case you need to add something else to the Grid page, you can do that via your block-container or directly via the Layout.<\/p>\n<p>This is the<em> Grid&#8217;s Layout:<\/em><\/p>\n<p><em>app\/code\/Vendor\/Rules\/view\/adminhtml\/layout\/vendor_rules_example_rule_index.xml<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?xml version=\"1.0\"?&gt;\n&lt;page xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:View\/Layout\/etc\/page_configuration.xsd\"&gt;\n    &lt;body&gt;\n    &lt;referenceContainer name=\"content\"&gt;\n        &lt;block class=\"Vendor\\Rules\\Block\\Adminhtml\\Example\\Rule\" name=\"adminhtml.block.example.rule.grid.container\"&gt;\n            &lt;block class=\"Magento\\Backend\\Block\\Widget\\Grid\" name=\"adminhtml.block.example.rule.grid\" as=\"grid\"&gt;\n                &lt;arguments&gt;\n                    &lt;argument name=\"id\" xsi:type=\"string\"&gt;example_rule_grid&lt;\/argument&gt;\n                    &lt;argument name=\"dataSource\" xsi:type=\"object\"&gt;Vendor\\Rules\\Model\\ResourceModel\\Rule\\Collection&lt;\/argument&gt;\n                    &lt;argument name=\"default_sort\" xsi:type=\"string\"&gt;sort_order&lt;\/argument&gt;\n                    &lt;argument name=\"default_dir\" xsi:type=\"string\"&gt;ASC&lt;\/argument&gt;\n                    &lt;argument name=\"save_parameters_in_session\" xsi:type=\"string\"&gt;1&lt;\/argument&gt;\n                &lt;\/arguments&gt;\n                &lt;block class=\"Magento\\Backend\\Block\\Widget\\Grid\\ColumnSet\" as=\"grid.columnSet\" name=\"adminhtml.example.rule.grid.columnSet\"&gt;\n                    &lt;arguments&gt;\n                        &lt;argument name=\"rowUrl\" xsi:type=\"array\"&gt;\n                            &lt;item name=\"path\" xsi:type=\"string\"&gt;vendor_rules\/*\/edit&lt;\/item&gt;\n                            &lt;item name=\"extraParamsTemplate\" xsi:type=\"array\"&gt;\n                                &lt;item name=\"id\" xsi:type=\"string\"&gt;getRuleId&lt;\/item&gt;\n                            &lt;\/item&gt;\n                        &lt;\/argument&gt;\n                    &lt;\/arguments&gt;\n                    &lt;block class=\"Magento\\Backend\\Block\\Widget\\Grid\\Column\" as=\"rule_id\"&gt;\n                        &lt;arguments&gt;\n                            &lt;argument name=\"header\" xsi:type=\"string\" translate=\"true\"&gt;ID&lt;\/argument&gt;\n                            &lt;argument name=\"index\" xsi:type=\"string\"&gt;rule_id&lt;\/argument&gt;\n                            &lt;argument name=\"column_css_class\" xsi:type=\"string\"&gt;col-id&lt;\/argument&gt;\n                            &lt;argument name=\"header_css_class\" xsi:type=\"string\"&gt;col-id&lt;\/argument&gt;\n                        &lt;\/arguments&gt;\n                    &lt;\/block&gt;\n                    &lt;block class=\"Magento\\Backend\\Block\\Widget\\Grid\\Column\" as=\"name\"&gt;\n                        &lt;arguments&gt;\n                            &lt;argument name=\"header\" xsi:type=\"string\" translate=\"true\"&gt;Rule&lt;\/argument&gt;\n                            &lt;argument name=\"index\" xsi:type=\"string\"&gt;name&lt;\/argument&gt;\n                        &lt;\/arguments&gt;\n                    &lt;\/block&gt;\n                    &lt;block class=\"Magento\\Backend\\Block\\Widget\\Grid\\Column\" as=\"is_active\"&gt;\n                        &lt;arguments&gt;\n                            &lt;argument name=\"header\" xsi:type=\"string\" translate=\"true\"&gt;Status&lt;\/argument&gt;\n                            &lt;argument name=\"index\" xsi:type=\"string\"&gt;is_active&lt;\/argument&gt;\n                            &lt;argument name=\"type\" xsi:type=\"string\"&gt;options&lt;\/argument&gt;\n                            &lt;argument name=\"options\" xsi:type=\"array\"&gt;\n                                &lt;item name=\"active\" xsi:type=\"array\"&gt;\n                                    &lt;item name=\"value\" xsi:type=\"string\"&gt;1&lt;\/item&gt;\n                                    &lt;item name=\"label\" xsi:type=\"string\" translate=\"true\"&gt;Active&lt;\/item&gt;\n                                &lt;\/item&gt;\n                                &lt;item name=\"inactive\" xsi:type=\"array\"&gt;\n                                    &lt;item name=\"value\" xsi:type=\"string\"&gt;0&lt;\/item&gt;\n                                    &lt;item name=\"label\" xsi:type=\"string\" translate=\"true\"&gt;Inactive&lt;\/item&gt;\n                                &lt;\/item&gt;\n                            &lt;\/argument&gt;\n                        &lt;\/arguments&gt;\n                    &lt;\/block&gt;\n                    &lt;block class=\"Magento\\Backend\\Block\\Widget\\Grid\\Column\" as=\"sort_order\"&gt;\n                        &lt;arguments&gt;\n                            &lt;argument name=\"header\" xsi:type=\"string\" translate=\"true\"&gt;Priority&lt;\/argument&gt;\n                            &lt;argument name=\"index\" xsi:type=\"string\"&gt;sort_order&lt;\/argument&gt;\n                        &lt;\/arguments&gt;\n                    &lt;\/block&gt;\n                    &lt;block class=\"Magento\\Backend\\Block\\Widget\\Grid\\Column\" as=\"from_date\"&gt;\n                        &lt;arguments&gt;\n                            &lt;argument name=\"header\" xsi:type=\"string\" translate=\"true\"&gt;Start&lt;\/argument&gt;\n                            &lt;argument name=\"type\" xsi:type=\"string\"&gt;date&lt;\/argument&gt;\n                            &lt;argument name=\"index\" xsi:type=\"string\"&gt;from_date&lt;\/argument&gt;\n                            &lt;argument name=\"column_css_class\" xsi:type=\"string\"&gt;col-date&lt;\/argument&gt;\n                            &lt;argument name=\"header_css_class\" xsi:type=\"string\"&gt;col-date&lt;\/argument&gt;\n                        &lt;\/arguments&gt;\n                    &lt;\/block&gt;\n                    &lt;block class=\"Magento\\Backend\\Block\\Widget\\Grid\\Column\" as=\"to_date\"&gt;\n                        &lt;arguments&gt;\n                            &lt;argument name=\"header\" xsi:type=\"string\" translate=\"true\"&gt;End&lt;\/argument&gt;\n                            &lt;argument name=\"type\" xsi:type=\"string\"&gt;date&lt;\/argument&gt;\n                            &lt;argument name=\"default\" xsi:type=\"string\"&gt;--&lt;\/argument&gt;\n                            &lt;argument name=\"index\" xsi:type=\"string\"&gt;to_date&lt;\/argument&gt;\n                            &lt;argument name=\"column_css_class\" xsi:type=\"string\"&gt;col-date&lt;\/argument&gt;\n                            &lt;argument name=\"header_css_class\" xsi:type=\"string\"&gt;col-date&lt;\/argument&gt;\n                        &lt;\/arguments&gt;\n                    &lt;\/block&gt;\n                &lt;\/block&gt;\n            &lt;\/block&gt;\n        &lt;\/block&gt;\n    &lt;\/referenceContainer&gt;\n    &lt;\/body&gt;\n&lt;\/page&gt;<\/pre>\n<p>Everything is placed inside of the page content.<\/p>\n<p>`&lt;<em>block class=&#8221;Vendor\\Rules\\Block\\Adminhtml\\Example\\Rule&#8221; &#8230;<\/em>&gt;&#8230;&lt;<em>\/block<\/em>&gt;` is our main container.<\/p>\n<p>Note that the container&#8217;s block and grid names are formed from the controller&#8217;s name that we mentioned in the Container. If you do this incorrectly, the Grid may fail to display.<\/p>\n<p>The Grid block itself: `&lt;<em>block class=&#8221;Magento\\Backend\\Block\\Widget\\Grid&#8221; name<\/em>=&#8221;adminhtml.block.example.rule.grid&#8221; as=&#8221;grid&#8221;&gt;`. Here, we need to fill in a number of arguments:<\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;arguments&gt;\n    &lt;argument name=\"id\" xsi:type=\"string\"&gt;example_rule_grid&lt;\/argument&gt;\n    &lt;argument name=\"dataSource\" xsi:type=\"object\"&gt;Vendor\\Rules\\Model\\ResourceModel\\Rule\\Collection&lt;\/argument&gt;\n    &lt;argument name=\"default_sort\" xsi:type=\"string\"&gt;sort_order&lt;\/argument&gt;\n    &lt;argument name=\"default_dir\" xsi:type=\"string\"&gt;ASC&lt;\/argument&gt;\n    &lt;argument name=\"save_parameters_in_session\" xsi:type=\"string\"&gt;1&lt;\/argument&gt;\n&lt;\/arguments&gt;<\/pre>\n<p>We are using our `<em>Vendor\\Rules\\Model\\ResourceModel\\Rule\\Collection<\/em>` collection as a source and define the sorting order.<\/p>\n<p>The `&lt;<em>block class=&#8221;Magento\\Backend\\Block\\Widget\\Grid\\ColumnSet&#8221; as=&#8221;grid.columnSet&#8221; name=&#8221;adminhtml.example.rule.grid.columnSet<\/em>&#8220;&gt;&#8230;&lt;<em>\/block<\/em>&gt;` block contains a number of columns. If you want to add your own columns, they should be added to the database and the Grid (if you want to see them):<\/p>\n<p>Now, let&#8217;s get down to creating and <a href=\"https:\/\/www.mageworx.com\/magento2-order-editor-extension.html\">editing<\/a> new rules. Let&#8217;s create the main container block for editing:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Block\/Adminhtml\/Example\/Rule\/Edit.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Block\\Adminhtml\\Example\\Rule;\n\nclass Edit extends \\Magento\\Backend\\Block\\Widget\\Form\\Container\n{\n    \/**\n     * Core registry\n     *\n     * @var \\Magento\\Framework\\Registry\n     *\/\n    protected $coreRegistry = null;\n\n    \/**\n     * @param \\Magento\\Backend\\Block\\Widget\\Context $context\n     * @param \\Magento\\Framework\\Registry $registry\n     * @param array $data\n     *\/\n    public function __construct(\n        \\Magento\\Backend\\Block\\Widget\\Context $context,\n        \\Magento\\Framework\\Registry $registry,\n        array $data = []\n    ) {\n        $this-&gt;coreRegistry = $registry;\n        parent::__construct($context, $data);\n    }\n\n    \/**\n     * Initialize form\n     * Add standard buttons\n     * Add \"Save and Continue\" button\n     *\n     * @return void\n     *\/\n    protected function _construct()\n    {\n        $this-&gt;_objectId = 'id';\n        $this-&gt;_controller = 'adminhtml_example_rule';\n        $this-&gt;_blockGroup = 'Vendor_Rules';\n\n        parent::_construct();\n\n        $this-&gt;buttonList-&gt;add(\n            'save_and_continue_edit',\n            [\n                'class' =&gt; 'save',\n                'label' =&gt; __('Save and Continue Edit'),\n                'data_attribute' =&gt; [\n                    'mage-init' =&gt; ['button' =&gt; ['event' =&gt; 'saveAndContinueEdit', 'target' =&gt; '#edit_form']],\n                ]\n            ],\n            10\n        );\n    }\n\n    \/**\n     * Getter for form header text\n     *\n     * @return \\Magento\\Framework\\Phrase\n     *\/\n    public function getHeaderText()\n    {\n        $rule = $this-&gt;coreRegistry-&gt;registry('current_rule');\n        if ($rule-&gt;getRuleId()) {\n            return __(\"Edit Rule '%1'\", $this-&gt;escapeHtml($rule-&gt;getName()));\n        } else {\n            return __('New Rule');\n        }\n    }\n\n}<\/pre>\n<p>When done, we should add the controllers title and the `<em>save<\/em>` and `<em>edit current model<\/em>` buttons in the Constructor. Also, here you should add the main text for of the block.<\/p>\n<p>This is a form itself:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Block\/Adminhtml\/Example\/Rule\/Edit\/Form.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Block\\Adminhtml\\Example\\Rule\\Edit;\n\nclass Form extends \\Magento\\Backend\\Block\\Widget\\Form\\Generic\n{\n    \/**\n     * Constructor\n     *\n     * @return void\n     *\/\n    protected function _construct()\n    {\n        parent::_construct();\n        $this-&gt;setId('example_rule_form');\n        $this-&gt;setTitle(__('Rule Information'));\n    }\n\n    \/**\n     * Prepare form before rendering HTML\n     *\n     * @return \\Magento\\Backend\\Block\\Widget\\Form\\Generic\n     *\/\n    protected function _prepareForm()\n    {\n        \/** @var \\Magento\\Framework\\Data\\Form $form *\/\n        $form = $this-&gt;_formFactory-&gt;create(\n            [\n                'data' =&gt; [\n                    'id' =&gt; 'edit_form',\n                    'action' =&gt; $this-&gt;getUrl('vendor_rules\/example_rule\/save'),\n                    'method' =&gt; 'post',\n                ],\n            ]\n        );\n        $form-&gt;setUseContainer(true);\n        $this-&gt;setForm($form);\n        return parent::_prepareForm();\n    }\n}<\/pre>\n<p>and tabs:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Block\/Adminhtml\/Example\/Rule\/Edit\/Tabs.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Block\\Adminhtml\\Example\\Rule\\Edit;\n\nclass Tabs extends \\Magento\\Backend\\Block\\Widget\\Tabs\n{\n    \/**\n     * Constructor\n     *\n     * @return void\n     *\/\n    protected function _construct()\n    {\n        parent::_construct();\n        $this-&gt;setId('rules_edit_tabs');\n        $this-&gt;setDestElementId('edit_form');\n        $this-&gt;setTitle(__('Rules'));\n    }\n}<\/pre>\n<p>We&#8217;ll have the two tabs: Ceneral model&#8217;s information and Conditions.<br \/>\n<em><br \/>\napp\/code\/Vendor\/Rules\/Block\/Adminhtml\/Example\/Rule\/Edit\/Tab\/Main.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Block\\Adminhtml\\Example\\Rule\\Edit\\Tab;\n\nuse Magento\\Backend\\Block\\Template\\Context;\nuse Magento\\Backend\\Block\\Widget\\Form\\Generic;\nuse Magento\\Backend\\Block\\Widget\\Tab\\TabInterface;\nuse Magento\\Framework\\Data\\FormFactory;\nuse Magento\\Framework\\Registry;\n\nclass Main extends Generic implements TabInterface\n{\n\n    \/**\n     * Constructor\n     *\n     * @param Context $context\n     * @param Registry $registry\n     * @param FormFactory $formFactory\n     * @param array $data\n     *\/\n    public function __construct(\n        Context $context,\n        Registry $registry,\n        FormFactory $formFactory,\n        array $data = []\n    ) {\n        parent::__construct($context, $registry, $formFactory, $data);\n    }\n\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function getTabLabel()\n    {\n        return __('Rule Information');\n    }\n\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function getTabTitle()\n    {\n        return __('Rule Information');\n    }\n\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function canShowTab()\n    {\n        return true;\n    }\n\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function isHidden()\n    {\n        return false;\n    }\n\n    \/**\n     * Prepare form before rendering HTML\n     *\n     * @return Generic\n     *\/\n    protected function _prepareForm()\n    {\n        $model = $this-&gt;_coreRegistry-&gt;registry('current_rule');\n\n        \/** @var \\Magento\\Framework\\Data\\Form $form *\/\n        $form = $this-&gt;_formFactory-&gt;create();\n        $form-&gt;setHtmlIdPrefix('rule_');\n\n        $fieldset = $form-&gt;addFieldset('base_fieldset', ['legend' =&gt; __('General Information')]);\n\n        if ($model-&gt;getId()) {\n            $fieldset-&gt;addField('rule_id', 'hidden', ['name' =&gt; 'rule_id']);\n        }\n\n        $fieldset-&gt;addField(\n            'name',\n            'text',\n            ['name' =&gt; 'name', 'label' =&gt; __('Rule Name'), 'title' =&gt; __('Rule Name'), 'required' =&gt; true]\n        );\n\n        $fieldset-&gt;addField(\n            'description',\n            'textarea',\n            [\n                'name' =&gt; 'description',\n                'label' =&gt; __('Description'),\n                'title' =&gt; __('Description'),\n                'style' =&gt; 'height: 100px;'\n            ]\n        );\n\n        $fieldset-&gt;addField(\n            'is_active',\n            'select',\n            [\n                'label' =&gt; __('Status'),\n                'title' =&gt; __('Status'),\n                'name' =&gt; 'is_active',\n                'required' =&gt; true,\n                'options' =&gt; ['1' =&gt; __('Active'), '0' =&gt; __('Inactive')]\n            ]\n        );\n\n        if (!$model-&gt;getId()) {\n            $model-&gt;setData('is_active', '1');\n        }\n\n        $fieldset-&gt;addField('sort_order', 'text', ['name' =&gt; 'sort_order', 'label' =&gt; __('Priority')]);\n\n        $dateFormat = $this-&gt;_localeDate-&gt;getDateFormat(\\IntlDateFormatter::SHORT);\n        $fieldset-&gt;addField(\n            'from_date',\n            'date',\n            [\n                'name' =&gt; 'from_date',\n                'label' =&gt; __('From'),\n                'title' =&gt; __('From'),\n                'input_format' =&gt; \\Magento\\Framework\\Stdlib\\DateTime::DATE_INTERNAL_FORMAT,\n                'date_format' =&gt; $dateFormat\n            ]\n        );\n        $fieldset-&gt;addField(\n            'to_date',\n            'date',\n            [\n                'name' =&gt; 'to_date',\n                'label' =&gt; __('To'),\n                'title' =&gt; __('To'),\n                'input_format' =&gt; \\Magento\\Framework\\Stdlib\\DateTime::DATE_INTERNAL_FORMAT,\n                'date_format' =&gt; $dateFormat\n            ]\n        );\n\n        $form-&gt;setValues($model-&gt;getData());\n\n        if ($model-&gt;isReadonly()) {\n            foreach ($fieldset-&gt;getElements() as $element) {\n                $element-&gt;setReadonly(true, true);\n            }\n        }\n\n        $this-&gt;setForm($form);\n\n        $this-&gt;_eventManager-&gt;dispatch('adminhtml_example_rule_edit_tab_main_prepare_form', ['form' =&gt; $form]);\n\n        return parent::_prepareForm();\n    }\n}<\/pre>\n<p>Conditions:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/Block\/Adminhtml\/Example\/Rule\/Edit\/Tab\/Conditions.php<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true\">&lt;?php\n\nnamespace Vendor\\Rules\\Block\\Adminhtml\\Example\\Rule\\Edit\\Tab;\n\nuse Magento\\Backend\\Block\\Widget\\Form\\Generic;\nuse Magento\\Backend\\Block\\Widget\\Tab\\TabInterface;\n\nclass Conditions extends Generic implements TabInterface\n{\n    \/**\n     * Core registry\n     *\n     * @var \\Magento\\Backend\\Block\\Widget\\Form\\Renderer\\Fieldset\n     *\/\n    protected $rendererFieldset;\n\n    \/**\n     * @var \\Magento\\Rule\\Block\\Conditions\n     *\/\n    protected $conditions;\n\n    \/**\n     * @param \\Magento\\Backend\\Block\\Template\\Context $context\n     * @param \\Magento\\Framework\\Registry $registry\n     * @param \\Magento\\Framework\\Data\\FormFactory $formFactory\n     * @param \\Magento\\Rule\\Block\\Conditions $conditions\n     * @param \\Magento\\Backend\\Block\\Widget\\Form\\Renderer\\Fieldset $rendererFieldset\n     * @param array $data\n     *\/\n    public function __construct(\n        \\Magento\\Backend\\Block\\Template\\Context $context,\n        \\Magento\\Framework\\Registry $registry,\n        \\Magento\\Framework\\Data\\FormFactory $formFactory,\n        \\Magento\\Rule\\Block\\Conditions $conditions,\n        \\Magento\\Backend\\Block\\Widget\\Form\\Renderer\\Fieldset $rendererFieldset,\n        array $data = []\n    ) {\n        $this-&gt;rendererFieldset = $rendererFieldset;\n        $this-&gt;conditions = $conditions;\n        parent::__construct($context, $registry, $formFactory, $data);\n    }\n\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function getTabLabel()\n    {\n        return __('Conditions');\n    }\n\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function getTabTitle()\n    {\n        return __('Conditions');\n    }\n\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function canShowTab()\n    {\n        return true;\n    }\n\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function isHidden()\n    {\n        return false;\n    }\n\n    \/**\n     * Prepare form before rendering HTML\n     *\n     * @return Generic\n     *\/\n    protected function _prepareForm()\n    {\n        $model = $this-&gt;_coreRegistry-&gt;registry('current_rule');\n\n        \/** @var \\Magento\\Framework\\Data\\Form $form *\/\n        $form = $this-&gt;_formFactory-&gt;create();\n        $form-&gt;setHtmlIdPrefix('rule_');\n\n        $renderer = $this-&gt;rendererFieldset-&gt;setTemplate(\n            'Magento_CatalogRule::promo\/fieldset.phtml'\n        )-&gt;setNewChildUrl(\n            $this-&gt;getUrl('vendor_rules\/example_rule\/newConditionHtml\/form\/rule_conditions_fieldset')\n        );\n\n        $fieldset = $form-&gt;addFieldset(\n            'conditions_fieldset',\n            [\n                'legend' =&gt; __(\n                    'Apply the rule only if the following conditions are met (leave blank for all products).'\n                )\n            ]\n        )-&gt;setRenderer(\n            $renderer\n        );\n\n        $fieldset-&gt;addField(\n            'conditions',\n            'text',\n            ['name' =&gt; 'conditions', 'label' =&gt; __('Conditions'), 'title' =&gt; __('Conditions')]\n        )-&gt;setRule(\n            $model\n        )-&gt;setRenderer(\n            $this-&gt;conditions\n        );\n\n        $form-&gt;setValues($model-&gt;getData());\n        $this-&gt;setForm($form);\n\n        return parent::_prepareForm();\n    }\n}<\/pre>\n<p>Also, let me draw your attention to the template that are used to render a fieldset: `<em>Magento_CatalogRule::promo\/fieldset.phtml<\/em>` and an address to recieve a new descendant: `<em>vendor_rules\/example_rule\/newConditionHtml\/form\/rule_conditions_fieldset<\/em>` that links to the `<em>app\/code\/Vendor\/Rules\/Controller\/Adminhtml\/Example\/Rule\/NewConditionHtml.php<\/em>` action we created earlier. In other words, all new descendants will derive from it.<\/p>\n<p>If you can&#8217;t add conditions, start the debug from this fieldset and condition.<\/p>\n<p>The correct answer for choosing another attribute in the conditions looks like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-6070\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5-1-1024x456.png\" alt=\"5\" width=\"1024\" height=\"456\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5-1-1024x456.png 1024w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5-1-150x67.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5-1-300x134.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5-1-768x342.png 768w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5-1.png 1902w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>You can understand that the controller works incorrectly if the window is not responding when choosing a new attribute in the conditions:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-6069\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5-1024x454.png\" alt=\"5\" width=\"1024\" height=\"454\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5-1024x454.png 1024w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5-150x66.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5-300x133.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5-768x340.png 768w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/5.png 1481w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>In this case you should reload the page first and then open your browser&#8217;s console to find a mistake in respone for the ajax request.<\/p>\n<p>This is the layout for the editing form:<\/p>\n<p><em>app\/code\/Vendor\/Rules\/view\/adminhtml\/layout\/vendor_rules_example_rule_edit.xml<\/em><\/p>\n<pre class=\"theme:github font:courier-new font-size:16 line-height:18 decode-attributes:false lang:default decode:true \">&lt;?xml version=\"1.0\"?&gt;\n&lt;page xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\" layout=\"admin-2columns-left\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:View\/Layout\/etc\/page_configuration.xsd\"&gt;\n    &lt;body&gt;\n    &lt;referenceContainer name=\"left\"&gt;\n        &lt;block class=\"Vendor\\Rules\\Block\\Adminhtml\\Example\\Rule\\Edit\\Tabs\" name=\"example_rule_edit_tabs\"&gt;\n            &lt;block class=\"Vendor\\Rules\\Block\\Adminhtml\\Example\\Rule\\Edit\\Tab\\Main\" name=\"example_rule_edit_tab_main\"\/&gt;\n            &lt;block class=\"Vendor\\Rules\\Block\\Adminhtml\\Example\\Rule\\Edit\\Tab\\Conditions\" name=\"example_rule_edit_tab_conditions\"\/&gt;\n            &lt;action method=\"addTab\"&gt;\n                &lt;argument name=\"name\" xsi:type=\"string\"&gt;main_section&lt;\/argument&gt;\n                &lt;argument name=\"block\" xsi:type=\"string\"&gt;example_rule_edit_tab_main&lt;\/argument&gt;\n            &lt;\/action&gt;\n            &lt;action method=\"addTab\"&gt;\n                &lt;argument name=\"name\" xsi:type=\"string\"&gt;conditions_section&lt;\/argument&gt;\n                &lt;argument name=\"block\" xsi:type=\"string\"&gt;example_rule_edit_tab_conditions&lt;\/argument&gt;\n            &lt;\/action&gt;\n        &lt;\/block&gt;\n    &lt;\/referenceContainer&gt;\n    &lt;referenceContainer name=\"content\"&gt;\n        &lt;block class=\"Vendor\\Rules\\Block\\Adminhtml\\Example\\Rule\\Edit\" name=\"example_rule_edit\"\/&gt;\n    &lt;\/referenceContainer&gt;\n    &lt;\/body&gt;\n&lt;\/page&gt;<\/pre>\n<p>The result should be the following:<\/p>\n<ul>\n<li>Main fields<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-6064\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/1-1024x442.png\" alt=\"1\" width=\"1024\" height=\"442\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/1-1024x442.png 1024w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/1-150x65.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/1-300x129.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/1-768x332.png 768w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/1.png 1858w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<ul>\n<li>Conditions<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-6065\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/2-1024x436.png\" alt=\"2\" width=\"1024\" height=\"436\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/2-1024x436.png 1024w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/2-150x64.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/2-300x128.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/2-768x327.png 768w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/2.png 1901w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-6066\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/3-1024x429.png\" alt=\"3\" width=\"1024\" height=\"429\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/3-1024x429.png 1024w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/3-150x63.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/3-300x126.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/3-768x322.png 768w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/09\/3.png 1905w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<h4 style=\"text-align: center;\"><\/h4>\n<h4 style=\"text-align: center;\"><strong>TO BE CONTINUED&#8230;<\/strong><\/h4>\n<p>See <a href=\"https:\/\/www.mageworx.com\/blog\/example-of-magento-2-module-with-conditions-model-and-fieldset-part-2\">the second part of the article<\/a> for more insights on the topic.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Reading Time: <\/span> <span class=\"rt-time\"> 13<\/span> <span class=\"rt-label rt-postfix\">minutes<\/span><\/span>While browsing Magento forums we often bump to the threads where developers are asking how to create an extension with custom rules and fieldset. Hence, we&#8217;ve decided to illustrate that on the example of a sample module that can be also used for further validating and other development purposes. Let&#8217;s roll in! To add a [&hellip;]<\/p>\n","protected":false},"author":15,"featured_media":6058,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[255,425],"tags":[436],"class_list":{"0":"post-6057","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-magento-2","8":"category-magento-how-tos","9":"tag-developer-diaries"},"_links":{"self":[{"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/posts\/6057","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/users\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/comments?post=6057"}],"version-history":[{"count":18,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/posts\/6057\/revisions"}],"predecessor-version":[{"id":16428,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/posts\/6057\/revisions\/16428"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/media\/6058"}],"wp:attachment":[{"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/media?parent=6057"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/categories?post=6057"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/tags?post=6057"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}