Since the DOM on the checkout page is loaded in an asynchronous way – I do not have access to some elements. Please suggest me how we can add a custom script to the checkout page after loading all the elements.
How to Add a JS Script After Full Loading Checkout Page in Magento 2
checkoutmagento2script
Related Solutions
Modify following class app/code/SR/DeliveryDate/Model/DeliveryDateConfigProvider.php
You can load data from database and added in getCustomOptionValue method.
namespace SR\DeliveryDate\Model;
use Magento\Checkout\Model\ConfigProviderInterface;
use Magento\Store\Model\ScopeInterface;
class DeliveryDateConfigProvider implements ConfigProviderInterface
{
const XPATH_FORMAT = 'sr_deliverydate/general/format';
const XPATH_DISABLED = 'sr_deliverydate/general/disabled';
const XPATH_HOURMIN = 'sr_deliverydate/general/hourMin';
const XPATH_HOURMAX = 'sr_deliverydate/general/hourMax';
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $storeManager;
/**
* @var \Magento\Framework\App\Config\ScopeConfigInterface
*/
protected $scopeConfig;
/**
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
*/
public function __construct(
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
) {
$this->storeManager = $storeManager;
$this->scopeConfig = $scopeConfig;
}
/**
* {@inheritdoc}
*/
public function getConfig()
{
$store = $this->getStoreId();
$disabled = $this->scopeConfig->getValue(self::XPATH_DISABLED, ScopeInterface::SCOPE_STORE, $store);
$hourMin = $this->scopeConfig->getValue(self::XPATH_HOURMIN, ScopeInterface::SCOPE_STORE, $store);
$hourMax = $this->scopeConfig->getValue(self::XPATH_HOURMAX, ScopeInterface::SCOPE_STORE, $store);
$format = $this->scopeConfig->getValue(self::XPATH_FORMAT, ScopeInterface::SCOPE_STORE, $store);
$noday = 0;
if($disabled == -1) {
$noday = 1;
}
$config = [
'shipping' => [
'delivery_date' => [
'format' => $format,
'disabled' => $disabled,
'noday' => $noday,
'hourMin' => $hourMin,
'hourMax' => $hourMax,
'customOptionValue' => $this->getCustomOptionValue()
]
]
];
return $config;
}
public function getStoreId()
{
return $this->storeManager->getStore()->getStoreId();
}
public function getCustomOptionValue()
{
return [
'option1' => 'Option 1',
'option2' => 'Option 2',
'option3' => 'Option 3'
];
}
}
app/code/SR/DeliveryDate/view/frontend/web/js/view/delivery-date-block.js
define([
'jquery',
'ko',
'uiComponent'
], function ($, ko, Component) {
'use strict';
return Component.extend({
defaults: {
template: 'SR_DeliveryDate/delivery-date-block',
customOptionValue: ''
},
initialize: function () {
this._super();
var disabled = window.checkoutConfig.shipping.delivery_date.disabled;
var noday = window.checkoutConfig.shipping.delivery_date.noday;
var hourMin = parseInt(window.checkoutConfig.shipping.delivery_date.hourMin);
var hourMax = parseInt(window.checkoutConfig.shipping.delivery_date.hourMax);
var format = window.checkoutConfig.shipping.delivery_date.format;
if(!format) {
format = 'yy-mm-dd';
}
var disabledDay = disabled.split(",").map(function(item) {
return parseInt(item, 10);
});
ko.bindingHandlers.datetimepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
var $el = $(element);
//initialize datetimepicker
if(noday) {
var options = {
minDate: 0,
dateFormat:format,
hourMin: hourMin,
hourMax: hourMax
};
} else {
var options = {
minDate: 0,
dateFormat:format,
hourMin: hourMin,
hourMax: hourMax,
beforeShowDay: function(date) {
var day = date.getDay();
if(disabledDay.indexOf(day) > -1) {
return [false];
} else {
return [true];
}
}
};
}
$el.datetimepicker(options);
var writable = valueAccessor();
if (!ko.isObservable(writable)) {
var propWriters = allBindingsAccessor()._ko_property_writers;
if (propWriters && propWriters.datetimepicker) {
writable = propWriters.datetimepicker;
} else {
return;
}
}
writable($(element).datetimepicker("getDate"));
},
update: function (element, valueAccessor) {
var widget = $(element).data("DateTimePicker");
//when the view model is updated, update the widget
if (widget) {
var date = ko.utils.unwrapObservable(valueAccessor());
widget.date(date);
}
}
};
return this;
},
initObservable: function () {
this._super()
.observe([
'customOptionValue'
]);
return this;
},
getCustomOption: function() {
return _.map(window.checkoutConfig.shipping.delivery_date.customOptionValue, function(value, key) {
return {
'value': key,
'label': value
}
});
}
});
});
Your select input will be:
<select name="custom_option"
class="select"
data-bind="
options: getCustomOption(),
optionsValue: 'value',
optionsText: 'label',
optionsCaption: $t('Option'),
value: customOptionValue">
</select>
In your xml add below code,
<referenceContainer name="after.body.start">
<block name="custom">
<arguments>
<argument name="text" xsi:type="string"><![CDATA[<script type="text/javascript" src="js/custom.js"></script>]]></argument>
</arguments>
</block>
</referenceContainer>
In case above code not works, you can do it by adding a phtml and declaring script in that phtml.
<referenceContainer name="before.body.end">
<block template="Namespace_Modulename::custom.phtml" name="meaningful_name"/>
</referenceContainer>
In custom phtml, declare your script,
<script type="text/javascript">Your script</script>
Best Answer
To add javascript file in checkout page you should extend
checkout_index_index.xml
inside theme layout for magento checkout module or your custom module frontend layout folder, and add the following:to wait until all the element loaded, you can check which element is the last one being rendered (example: .payment-method). Inside the javacript function you can make code to wait until this last element exists inside your js file: