Magento 2 – How to Add Custom Field Before Place Order Button and Get Value in Observer

magento2onepage-checkout

I am creating one custom column in sales_order table.

I want to add that custom field before place order button and i have to save that field in sales_order table.

For save the value i want to get that value in observer

How can i add that custom field in magento 2 and save that value?

\Namespace\Modulename\view\frontend\layout\checkout_index_index.xml

In my custom module checkout_index_index.xml

<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">
                                        <!-- The new step you add -->
                                        <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="comment" xsi:type="array">
                                                            <item name="component" xsi:type="string">Namespace_Modulename/js/view/my-step-view</item>
                                                                <!--To display step content before shipping step "sortOrder" value should be < 1-->
                                                                <!--To display step content between shipping step and payment step  1 < "sortOrder" < 2 -->
                                                                <!--To display step content after payment step "sortOrder" > 2 -->
                                                            <item name="sortOrder" xsi:type="string">2</item>
                                                            <item name="children" xsi:type="array">
                                                                <!--add here child component declaration for your step-->
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
    </referenceBlock>
</body>
</page>

\Namespace\Modulename\view\frontend\web\js\view\my-step-view.js

define(
[
    'jquery',
    'ko',
    'uiComponent',
    'Magento_Checkout/js/model/quote'
],
function (
   $, ko, Component, quote
) {
    'use strict';
    /**
    *
    * mystep - is the name of the component's .html template, 
    * your_module_dir - is the name of the your module directory.
    * 
    */
    return Component.extend({
        defaults: {
            template: 'Namespace_Modulename/mystep'
        },

        //add here your logic to display step,
        isVisible: ko.observable(true),

        /**
        *
        * @returns {*}
        */

    });
  }
  );

\Namespace\Modulename\view\frontend\web\template\mystep.html

<li id="step_code" data-bind="fadeVisible: isVisible">
<div class="step-title" data-bind="i18n: 'Step Title'" data-role="title"></div>
<div id="checkout-step-title"
     class="step-content"
     data-role="content">

    <form data-bind="" novalidate="novalidate">
        <div class="actions-toolbar">
            <div class="primary">
              <input class="input-text" type="text" data-bind="
                    value: value,
                    valueUpdate: 'keyup',
                    hasFocus: focused,
                    attr: {
                        name: order_comment,
                        placeholder: placeholder,
                        id: uid
                    }" />
            </div>
        </div>
    </form>
</div>
</li>

Best Answer

checkout_index_index.xml

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<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="payments-list" xsi:type="array">
                                                            <item name="children" xsi:type="array">
                                                                <item name="order-comment" xsi:type="array">
                                                                    <item name="component" xsi:type="string">Namespace_Modulename/js/view/comment</item>
                                                                    <item name="displayArea" xsi:type="string">before-place-order</item>
                                                                    <item name="dataScope" xsi:type="string">checkoutcomment</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>

In comment.js

define(
    [
        'ko',
        'jquery',
        'uiComponent'
    ],
    function (ko, $, Component) {
        'use strict';
        return Component.extend({
            defaults: {
                template: 'Namespace_Modulename/checkout/comment'
            }
        });
    }

);

in comment.html

<form data-role="order-comments" method="post">
    <label><strong>Order Comment</strong></label>
    <textarea class="input-text" name="order_comment" type="text"></textarea>
</form>

make a column in qoute and sales_order column In observer save like this

    $order = $observer->getOrder();
    $quoteRepository = $this->_objectManager->create('Magento\Quote\Model\QuoteRepository');
    $quote = $quoteRepository->get($order->getQuoteId());
    $order->setOrderComment( $quote->getOrderComment() );