How to Add Custom Field in Checkout Page Below Payment Method List in Magento 2
Magento 2 CMS is widely preferred to run online businesses in various niches.
As the CMS is flexible for customization, modern business requirements can be easily fulfilled. One such example is to add custom field in checkout page just after payment method list in Magento 2. Likewise you can also add custom field below Apply Discount code in Magento 2, to make the customers click it and let them explore detailed offer benefits.
Also as being an admin you can get week days list in Magento 2 system configuration for when a customer can book an appointment, or select the days on which the store will offer delivery.
This post shows the programmatic solution for the same.
For example. you need the customer to agree with something apart from the default Magento 2 terms and conditions, you can implement a custom checkbox.
Or, you can add the gift wrap checkbox using the below code. If you want to encourage the customers to donate some amount with each purchase, you can add a checkbox field which when the customer will tick, a fixed amount will be added to the cart total automatically. Or even If you want to restrict access to certain payment methods and make them visible only to the admin, you can use the “Make a Payment Method Visible Only to Admin” feature.
Any of the above scenarios can be implemented or other custom fields can be added as shown in the figure below:
The example here is about adding a custom checkbox in the checkout page, saving its value in the database table, and displaying the same in the admin panel.
Steps to Add custom field in checkout page just after payment method list in Magento 2:
Step 1: To add custom field in the table
Create InstallData.php file under Vendor\Module\Setup\
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
<?php namespace Vendor\Module\Setup; use Magento\Framework\Setup\InstallDataInterface; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Customer\Model\Customer; use Magento\Customer\Setup\CustomerSetupFactory; class InstallData implements InstallDataInterface { private $customerSetupFactory; /** * Constructor * * @param \Magento\Customer\Setup\CustomerSetupFactory $customerSetupFactory */ public function __construct( CustomerSetupFactory $customerSetupFactory ) { $this->customerSetupFactory = $customerSetupFactory; } /** * {@inheritdoc} */ public function install( ModuleDataSetupInterface $setup, ModuleContextInterface $context ) { $installer = $setup; $installer->startSetup(); $installer->getConnection()->addColumn( $installer->getTable('quote'), 'agree', [ 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_BOOLEAN, 'visible' => true, 'default' => 0, 'comment' => 'Custom Condition' ] ); $installer->getConnection()->addColumn( $installer->getTable('sales_order'), 'agree', [ 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_BOOLEAN, 'visible' => true, 'default' => 0, 'comment' => 'Custom Condition' ] ); } } |
Step 2: To Create extension attribute and add checkbox just after payment methods and Save that field in Quote table
Create extension_attributes.xml file under Vendor\Module\etc\
1 2 3 4 5 6 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Quote\Api\Data\AddressInterface"> <attribute code="agree" type="string" /> </extension_attributes> </config> |
Create checkout_index_index.xml file under Vendor\Module\view\frontend\layout\
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="checkout.root"> <arguments> <argument name="jsLayout" xsi:type="array"> <item name="components" xsi:type="array"> <item name="checkout" xsi:type="array"> <item name="children" xsi:type="array"> <item name="steps" xsi:type="array"> <item name="children" xsi:type="array"> <item name="billing-step" xsi:type="array"> <item name="children" xsi:type="array"> <item name="payment" xsi:type="array"> <item name="children" xsi:type="array"> <item name="afterMethods" xsi:type="array"> <item name="children" xsi:type="array"> <item name="custom-checkbox" xsi:type="array"> <item name="component" xsi:type="string">Vendor_Module/js/checkout/customJs</item> <item name="displayArea" xsi:type="string">before-place-order</item> <item name="sortOrder" xsi:type="string">3</item> <item name="dataScope" xsi:type="string">checkoutcomments</item> <item name="provider" xsi:type="string">checkoutProvider</item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </argument> </arguments> </referenceBlock> </body> </page> |
Create customJs.js file under Vendor\Module\view\frontend\web\js\checkout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
define( [ 'ko', 'jquery', 'uiComponent', 'mage/url' ], function (ko, $, Component,url) { 'use strict'; return Component.extend({ defaults: { template: 'Vendor_Module/checkout/customCheckbox' }, initObservable: function () { this._super() .observe({ CheckVals: ko.observable(false) }); var checkVal=0; self = this; this.CheckVals.subscribe(function (newValue) { var linkUrls = url.build('module/checkout/saveInQuote'); if(newValue) { checkVal = 1; } else{ checkVal = 0; } $.ajax({ showLoader: true, url: linkUrls, data: {checkVal : checkVal}, type: "POST", dataType: 'json' }).done(function (data) { console.log('success'); }); }); return this; } }); } ); |
Create customCheckbox.html file under Vendor\Module\view\frontend\web\template\checkout
1 |
<input type="checkbox" name="customCheckbox" value="" data-bind='checked: CheckVals'/><div> Check to Agree </div> |
Create saveInQuote.php file under Vendor\Module\Controller\Checkout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
<?php namespace Vendor\Module\Controller\Checkout; use Magento\Framework\App\Action\Context; use Magento\Framework\Controller\Result\ForwardFactory; use Magento\Framework\View\LayoutFactory; use Magento\Checkout\Model\Cart; use Magento\Framework\App\Action\Action; use Magento\Checkout\Model\Session; use Magento\Quote\Model\QuoteRepository; class saveInQuote extends Action { protected $resultForwardFactory; protected $layoutFactory; protected $cart; public function __construct( Context $context, ForwardFactory $resultForwardFactory, LayoutFactory $layoutFactory, Cart $cart, Session $checkoutSession, QuoteRepository $quoteRepository ) { $this->resultForwardFactory = $resultForwardFactory; $this->layoutFactory = $layoutFactory; $this->cart = $cart; $this->checkoutSession = $checkoutSession; $this->quoteRepository = $quoteRepository; parent::__construct($context); } public function execute() { $checkVal = $this->getRequest()->getParam('checkVal'); $quoteId = $this->checkoutSession->getQuoteId(); $quote = $this->quoteRepository->get($quoteId); $quote->setAgree($checkVal); $quote->save(); } } |
Step 3: To Save that custom field in Sales_Order table
Create events.xml file under Vendor\Module\etc\
1 2 3 4 5 6 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="sales_model_service_quote_submit_before"> <observer name="custom_checkbox_code_order_place_before_action" instance="Vendor\Module\Observer\PlaceOrder"/> </event> </config> |
Create PlaceOrder.php file under Vendor\Module\Observer\
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<?php namespace Vendor\Module\Observer; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Quote\Model\QuoteFactory; use Psr\Log\LoggerInterface; class PlaceOrder implements ObserverInterface { /** * @var \Psr\Log\LoggerInterface */ protected $_logger; /** * @var \Magento\Customer\Model\Session */ protected $quoteFactory; /** * Constructor * * @param \Psr\Log\LoggerInterface $logger */ public function __construct(LoggerInterface $logger, QuoteFactory $quoteFactory) { $this->_logger = $logger; $this->quoteFactory = $quoteFactory; } public function execute(Observer $observer) { $order = $observer->getOrder(); $quoteId = $order->getQuoteId(); $quote = $this->quoteFactory->create()->load($quoteId); $order->setAgree($quote->getAgree()); $order->save(); } } |
Create routes.xml file at Vendor\Module\etc\frontend
1 2 3 4 5 6 7 8 9 |
<?xml version="1.0"?> <config xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <router id="standard"> <route id="Vendor_Module" frontName="module"> <module name="Vendor_Module"/> </route> </router> </config> |
Step 4: To Display custom field value in admin side order view
Create sales_order_view.xml file under Vendor\Module\view\adminhtml\layout
1 2 3 4 5 6 7 8 |
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="order_info"> <block class="Vendor\Module\Block\Adminhtml\Order\View\DisplayCustomValue" name="sales_order_view_custom_value" template="order/view/displayCustomValue.phtml" /> </referenceBlock> </body> </page> |
Create displayCustomValue.phtml file under Vendor\Module\view\adminhtml\templates\order\view
1 2 3 |
<h4>Custom Condition Added : <?php $CheckValue = $block->getAgree(); ($CheckValue) ? echo 'Yes' : echo 'No'; ?> </h4> |
Create displayCustomValue.php file under Vendor\Module\Block\Adminhtml\Order\View\
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?php namespace Vendor\Module\Block\Adminhtml\Order\View; use Magento\Sales\Api\Data\OrderInterface; class DisplayCustomValue extends \Magento\Backend\Block\Template { public function __construct( \Magento\Backend\Block\Widget\Context $context, OrderInterface $orderInterface, array $data = [] ) { $this->orderInterface = $orderInterface; parent::__construct($context, $data); } public function getAgree(){ $orderId = $this->getRequest()->getParam('order_id'); $order = $this->orderInterface->load($orderId); return $order->getAgree(); } } |
That’s it.
Any other doubts about this solution can be mentioned in the Comments section below.
I’d be happy to help.
Also, do share the solution with the Magento Community via social media.
Also Read:
- How to Configure Zero Subtotal Checkout in Magento 2
- How to Convert Custom Field From Quote Item to Order Item in Magento 2
Additionally, if you want to add a custom field on the checkout page at a different position with additional features, you may as well use the third-party extension to ease your task!
Thank you.
Sanjay Jethva
Sanjay is the co-founder and CTO of Meetanshi with hands-on expertise with Magento since 2011. He specializes in complex development, integrations, extensions, and customizations. Sanjay is one the top 50 contributor to the Magento community and is recognized by Adobe.
His passion for Magento 2 and Shopify solutions has made him a trusted source for businesses seeking to optimize their online stores. He loves sharing technical solutions related to Magento 2 & Shopify.
26 Comments
I want to add custom text field below payment methods in checkout page by taking this as a reference. .But if we are using an external payment method like billdesk will it works fine and saves this custom field value on placing order. .will ithis code works fine?
Hey Chaitanya, Yes Adding it in payment section it will work,
And call custom js than probably it will work fine.
How to add custom drop down & save data on database ?
Hello Raju,
For that, you need to change customCheckbox.html file located under Vendor\Module\view\frontend\web\template\checkout
and you also need to change table column , InstallColumn.php and displayCustomValue.phtml as per your requirements.
Thank You
hi,
but its is not working for 2.4.3 version can u pls help me
Hello Sai,
The above code is already working for Magento 2.4.3.
What kind of issue you are facing?
Thank You
Hello,
Everything works fine except that when the box checked is not checked, I am redirected to the bank. I wish I got an error message when this happens.
Thanks.
Hello Jaskend,
The above code works fine from our end.
Compare the code again and also check your console log and log file if same issue persists.
Thank You
Hello, It’s nice blog and working fine but I want to add Select Option and get it’s value in js can you please share how to do that.
Hello Partab,
Thanks for the appreciation.
Regarding your query, you need to follow the below steps:
Edit installData.php to change the datatype field
fill select options using html file
Find selected option on change event and pass its value in the parameter
and save in a table
Thank You
Hello,
I have tried this and yes the agree checkbox field is working fine but when I change the Checkbox to Textbox the details are not stored in the database.
Will you please suggest
Hello Kuldeep
You can use the below code in customCheckbox.html to add a textbox
plus, you need to change the type in database, InstallData.php
Thank You
Hello
I have show magento popup on the checkbox click
this is work or not
Hello Ambient,
Yes. You can display popup on Checkbox click.
For that you have to do code for checkbox click then check if it is checked or not and then add code for open popup.
$(‘#checkbox_id’).click(function () {
if($(this).is(‘:checked’)) {
// Code To Show popup window
$(‘.custom-popup’).modal(‘openModal’);
}
});
Thank You
Hi how do you make it checked by default?
Hello Chris,
Set the value of CheckVals =1 by default in data-bind=’checked: CheckVals’
Thank You
I am curious why you are using both a db schema as well as an extension_attribute to save the data. Is this not duplicating the data in 2 areas?
Hello Robert,
No, it’s working fine from our end.
Extension attribute is used for extra variable value passing and to create and save value in table we create db schema.
Thank You
It doesn’t work on Magento 2.4.2, doesn’t load the checkbox and doesn’t find customJs.
Hello Marcelo,
Custom js is user defined js.
Magento 2 does not contains custom.js https://d.pr/HIzvwe .
Please follow all the given steps from the blog.
Thank You
It is very useful tutorial, But i want to add text field instead of checkbox. I am trying by reference of this tutorial but I facing some errors. Can you please help me .
Hey,
Thank you for the appreciation!
Use the below code in customCheckbox.html to add a textbox
Thank You.
Very Useful , Thank you.
but please i need hint to know How can i display value of gift message after payment method.
Hello,
Thank you for the appreciation!
You can get the value of the gift message by getting a gift message value in the function and then use this function in the template(.html) file.
Thank You.
Helped me a lot, thanks !
You just forget the routes.xml file and the event.xml file is wrong, the correct is events.xml
But it’s a detail.
Hello,
I’ve updated the code, please check it out.
Thank you for drawing attention.