Validation of the terms and conditions (custom module)
-
07-01-2021 - |
Domanda
I've made a custom module which enables me to have the T&C checkbox moved beneath the payment methods and the place order button inside the summary div, like so:
Now, whenever I select a payment method, check the box from the Terms and Conditions and press 'Place Order', the following pops up:
I've tried the following, but unfortunately no luck:
Magento 2 - move terms and conditions position in checkout
The Ajax payload after submitting order:
When using the checkout without the module, the content of the payload (payment-information) has:
extension_attributes: {agreement_ids: ["1"]}
agreement_ids: ["1"]
While when using my custom module, it's as follows:
extension_attributes: {agreement_ids: [""]}
agreement_ids: [""]
Thus it's empty... this probably seems to be the problem. How do I fix this?
CODE
module.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Vendor_Checkout" setup_version="1.0.0">
<sequence>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
checkout_index_index.xml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<css src="Vendor_Checkout::css/checkout.css"/>
</head>
<body>
<!-- Disabling the T&C checkbox under payment methods -->
<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="before-place-order" xsi:type="array">
<item name="componentDisabled" xsi:type="boolean">true</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
<!-- Moving terms and conditions after payment methods -->
<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="agreements" xsi:type="array">
<item name="component" xsi:type="string">Magento_CheckoutAgreements/js/view/checkout-agreements</item>
<item name="sortOrder" xsi:type="string">100</item>
<item name="displayArea" xsi:type="string">before-place-order</item>
<item name="dataScope" xsi:type="string">checkoutAgreements</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
</item>
<item name="agreements-validator" xsi:type="array">
<item name="component" xsi:type="string">Magento_CheckoutAgreements/js/view/agreement-validation</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
<!-- Moving place order button to sidebar -->
<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="sidebar" xsi:type="array">
<item name="children" xsi:type="array">
<item name="summary" xsi:type="array">
<item name="children" xsi:type="array">
<item name="children" xsi:type="array">
<item name="component" xsi:type="string">Vendor_Checkout/js/view/payment</item>
<item name="config" xsi:type="array">
<item name="template" xsi:type="string">Vendor_Checkout/button</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
web/template/button.html
<!-- ko if: (isVisible()) -->
<div class="actions-toolbar-trigger" id="place-order-trigger-wrapper">
<button type="button" class="button action primary" id="place-order-trigger" value="Place Order" >
<span data-bind="i18n: 'Place Order'">Place Order</span>
</button>
</div>
<!-- /ko -->
web/js/view/payment.js
define(
[
'jquery',
'ko',
'Magento_Checkout/js/view/summary',
'Magento_Checkout/js/model/step-navigator'
],
function(
$,
ko,
Component,
stepNavigator
) {
'use strict';
console.log('Running');
return Component.extend({
isVisible: function () {
return stepNavigator.isProcessed('shipping');
},
initialize: function () {
$(function() {
$('body').on("click", '#place-order-trigger', function () {
// Parse JSON here somehow?
$(".payment-method._active").find('.action.primary.checkout').trigger( 'click' );
});
});
var self = this;
this._super();
}
});
}
);
Soluzione
So, after being absent for a while I've found what causes the agreements to not be validated.
There is this file called agreements-assigner.js
, located in
Module_CheckoutAgreements/view/frontend/web/js/model
In this file, there is a variable called agreementForm
. This variable is assigned to the checkbox of the terms and agreements. Originally like this:
agreementForm = $('.payment-method._active div[data-role=checkout-agreements] input');
But of course, I moved the checkbox out of it's original location, so this path to the checkbox does not exist anymore.
If you, for example, change the variable as follows:
agreementForm = $('div[data-role=checkout-agreements] input');
The .js-file is able to locate your checkout agreements checkbox! Now your order can be placed succesfully.
A rather simple fix. I was trying to fix it using custom .js and stuff, and totally oversaw this file... ;)
NOTE: do not edit the core file directly. Rather copy it to your module or theme and alter the file according to your needs.
Altri suggerimenti
add following line in your custom module
app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements.js line no- 48 to 77
/**
* build a unique id for the term checkbox
*
* @param {Object} context - the ko context
* @param {Number} agreementId
*/
getCheckboxId: function (context, agreementId) {
var paymentMethodName = '',
paymentMethodRenderer = context.$parents[1];
// corresponding payment method fetched from parent context
if (paymentMethodRenderer) {
// item looks like this: {title: "Check / Money order", method: "checkmo"}
paymentMethodName = paymentMethodRenderer.item ?
paymentMethodRenderer.item.method : '';
}
return 'agreement_' + paymentMethodName + '_' + agreementId;
},
/**
* Init modal window for rendered element
*
* @param {Object} element
*/
initModal: function (element) {
agreementsModal.createModal(element);
}
});
});
change in file Magento/CheckoutAgreements/view/frontend/web/template/checkout/checkout-agreements.html
Replace
'id': 'agreement_' + agreementId,
in line 14
with
'id': $parent.getCheckboxId($parentContext, agreementId),
Replace
<label data-bind="attr: {'for': 'agreement_' + agreementId}">
with
<label data-bind="attr: {'for': $parent.getCheckboxId($parentContext, agreementId)}">
in line 18
Reference: https://github.com/magento/magento2/commit/14b9b9813c9a16c0c45505885503cfb71bc4eb8d