Try to follow all step:
Step 1: SR/ModifiedCheckout/etc/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="SR_ModifiedCheckout" setup_version="2.0.0">
<sequence>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
Step 2: SR/ModifiedCheckout/registration.php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'SR_ModifiedCheckout',
__DIR__
);
Step 3: SR/ModifiedCheckout/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\Block\Checkout\LayoutProcessor">
<plugin name="sr_modified_checkout_layout_processor" type="SR\ModifiedCheckout\Plugin\Block\LayoutProcessor" sortOrder="1"/>
</type>
</config>
Step 4: SR/ModifiedCheckout/Plugin/Block/LayoutProcessor.php
namespace SR\ModifiedCheckout\Plugin\Block;
use Magento\Customer\Model\AttributeMetadataDataProvider;
use Magento\Ui\Component\Form\AttributeMapper;
use Magento\Checkout\Block\Checkout\AttributeMerger;
use Magento\Checkout\Model\Session as CheckoutSession;
class LayoutProcessor
{
/**
* @var AttributeMetadataDataProvider
*/
public $attributeMetadataDataProvider;
/**
* @var AttributeMapper
*/
public $attributeMapper;
/**
* @var AttributeMerger
*/
public $merger;
/**
* @var CheckoutSession
*/
public $checkoutSession;
/**
* @var null
*/
public $quote = null;
/**
* LayoutProcessor constructor.
*
* @param AttributeMetadataDataProvider $attributeMetadataDataProvider
* @param AttributeMapper $attributeMapper
* @param AttributeMerger $merger
* @param CheckoutSession $checkoutSession
*/
public function __construct(
AttributeMetadataDataProvider $attributeMetadataDataProvider,
AttributeMapper $attributeMapper,
AttributeMerger $merger,
CheckoutSession $checkoutSession
) {
$this->attributeMetadataDataProvider = $attributeMetadataDataProvider;
$this->attributeMapper = $attributeMapper;
$this->merger = $merger;
$this->checkoutSession = $checkoutSession;
}
/**
* Get Quote
*
* @return \Magento\Quote\Model\Quote|null
*/
public function getQuote()
{
if (null === $this->quote) {
$this->quote = $this->checkoutSession->getQuote();
}
return $this->quote;
}
/**
* @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
* @param array $jsLayout
* @return array
*/
public function aroundProcess(
\Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
\Closure $proceed,
array $jsLayout
) {
$jsLayoutResult = $proceed($jsLayout);
if($this->getQuote()->isVirtual()) {
return $jsLayoutResult;
}
if(isset($jsLayoutResult['components']['checkout']['children']['steps']['children']['shipping-step']['children']
['shippingAddress']['children']['shipping-address-fieldset'])) {
$jsLayoutResult['components']['checkout']['children']['steps']['children']['shipping-step']
['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['street']['children'][0]['placeholder'] = __('Street Address');
$jsLayoutResult['components']['checkout']['children']['steps']['children']['shipping-step']
['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['street']['children'][1]['placeholder'] = __('Street line 2');
$elements = $this->getAddressAttributes();
$jsLayoutResult['components']['checkout']['children']['steps']['children']['shipping-step']
['children']['shippingAddress']['children']['billing-address'] = $this->getCustomBillingAddressComponent($elements);
$jsLayoutResult['components']['checkout']['children']['steps']['children']['shipping-step']
['children']['shippingAddress']['children']['billing-address']['children']['form-fields']['children']['street']['children'][0]['placeholder'] = __('Street Address');
$jsLayoutResult['components']['checkout']['children']['steps']['children']['shipping-step']
['children']['shippingAddress']['children']['billing-address']['children']['form-fields']['children']['street']['children'][1]['placeholder'] = __('Street line 2');
}
return $jsLayoutResult;
}
/**
* Get all visible address attribute
*
* @return array
*/
private function getAddressAttributes()
{
/** @var \Magento\Eav\Api\Data\AttributeInterface[] $attributes */
$attributes = $this->attributeMetadataDataProvider->loadAttributesCollection(
'customer_address',
'customer_register_address'
);
$elements = [];
foreach ($attributes as $attribute) {
$code = $attribute->getAttributeCode();
if ($attribute->getIsUserDefined()) {
continue;
}
$elements[$code] = $this->attributeMapper->map($attribute);
if (isset($elements[$code]['label'])) {
$label = $elements[$code]['label'];
$elements[$code]['label'] = __($label);
}
}
return $elements;
}
/**
* Prepare billing address field for shipping step for physical product
*
* @param $elements
* @return array
*/
public function getCustomBillingAddressComponent($elements)
{
return [
'component' => 'SR_ModifiedCheckout/js/view/billing-address',
'displayArea' => 'billing-address',
'provider' => 'checkoutProvider',
'deps' => ['checkoutProvider'],
'dataScopePrefix' => 'billingAddress',
'children' => [
'form-fields' => [
'component' => 'uiComponent',
'displayArea' => 'additional-fieldsets',
'children' => $this->merger->merge(
$elements,
'checkoutProvider',
'billingAddress',
[
'country_id' => [
'sortOrder' => 115,
],
'region' => [
'visible' => false,
],
'region_id' => [
'component' => 'Magento_Ui/js/form/element/region',
'config' => [
'template' => 'ui/form/field',
'elementTmpl' => 'ui/form/element/select',
'customEntry' => 'billingAddress.region',
],
'validation' => [
'required-entry' => true,
],
'filterBy' => [
'target' => '${ $.provider }:${ $.parentScope }.country_id',
'field' => 'country_id',
],
],
'postcode' => [
'component' => 'Magento_Ui/js/form/element/post-code',
'validation' => [
'required-entry' => true,
],
],
'company' => [
'validation' => [
'min_text_length' => 0,
],
],
'fax' => [
'validation' => [
'min_text_length' => 0,
],
],
'telephone' => [
'config' => [
'tooltip' => [
'description' => __('For delivery questions.'),
],
],
],
]
),
],
],
];
}
}
Step 5: SR/ModifiedCheckout/view/frontend/layout/checkout_index_index.xml
<?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="shipping-step" xsi:type="array">
<item name="children" xsi:type="array">
<item name="shippingAddress" xsi:type="array">
<item name="config" xsi:type="array">
<item name="template" xsi:type="string">SR_ModifiedCheckout/address</item>
</item>
</item>
<item name="overwriteShippingComponent" xsi:type="array">
<item name="component" xsi:type="string">SR_ModifiedCheckout/js/view/shipping</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
Step 6:SR/ModifiedCheckout/view/frontend/web/js/view/billing-address.js
/*jshint browser:true*/
/*global define*/
define(
[
'ko',
'underscore',
'jquery',
'Magento_Ui/js/form/form',
'Magento_Customer/js/model/customer',
'Magento_Customer/js/model/address-list',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/action/create-billing-address',
'Magento_Checkout/js/action/select-billing-address',
'Magento_Checkout/js/checkout-data',
'Magento_Checkout/js/model/checkout-data-resolver',
'Magento_Customer/js/customer-data',
'Magento_Checkout/js/action/set-billing-address',
'Magento_Ui/js/model/messageList',
'mage/translate'
],
function (
ko,
_,
$,
Component,
customer,
addressList,
quote,
createBillingAddress,
selectBillingAddress,
checkoutData,
checkoutDataResolver,
customerData,
setBillingAddressAction,
globalMessageList,
$t
) {
'use strict';
var newAddressOption = {
/**
* Get new address label
* @returns {String}
*/
getAddressInline: function () {
return $t('New Address');
},
customerAddressId: null
},
countryData = customerData.get('directory-data'),
addressOptions = addressList().filter(function (address) {
return address.getType() == 'customer-address';
});
addressOptions.push(newAddressOption);
return Component.extend({
defaults: {
template: 'SR_ModifiedCheckout/billing-address'
},
currentBillingAddress: quote.billingAddress,
addressOptions: addressOptions,
customerHasAddresses: addressOptions.length > 1,
/**
* Init component
*/
initialize: function () {
this._super();
},
/**
* @return {exports.initObservable}
*/
initObservable: function () {
this._super()
.observe({
selectedAddress: null,
isAddressFormVisible: false,
isAddressSameAsShipping: true,
saveInAddressBook: 1,
isAddressFormListVisible:false
});
return this;
},
canUseShippingAddress: ko.computed(function () {
return !quote.isVirtual() && quote.shippingAddress() && quote.shippingAddress().canUseForBilling();
}),
/**
* @param {Object} address
* @return {*}
*/
addressOptionsText: function (address) {
return address.getAddressInline();
},
/**
* @return {Boolean}
*/
useShippingAddress: function () {
if (this.isAddressSameAsShipping()) {
this.isAddressFormVisible(false);
this.isAddressFormListVisible(false);
} else {
if(addressOptions.length == 1) {
this.isAddressFormVisible(true);
} else {
this.isAddressFormListVisible(true);
}
}
return true;
},
/**
* @param {Object} address
*/
onAddressChange: function (address) {
if(address) {
this.isAddressFormVisible(false);
} else {
this.isAddressFormVisible(true);
}
},
/**
* @param {int} countryId
* @return {*}
*/
getCountryName: function (countryId) {
return countryData()[countryId] != undefined ? countryData()[countryId].name : '';
},
/**
* Get code
* @param {Object} parent
* @returns {String}
*/
getCode: function (parent) {
return _.isFunction(parent.getCode) ? parent.getCode() : 'shared';
}
});
}
);
Step 7:SR/ModifiedCheckout/view/frontend/web/js/view/shipping.js
define(
[
'jquery',
'underscore',
'Magento_Ui/js/form/form',
'ko',
'Magento_Customer/js/model/customer',
'Magento_Customer/js/model/address-list',
'Magento_Checkout/js/model/address-converter',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/action/create-shipping-address',
'Magento_Checkout/js/action/select-shipping-address',
'Magento_Checkout/js/view/shipping',
'Magento_Checkout/js/action/create-billing-address',
'Magento_Checkout/js/action/select-billing-address',
'Magento_Checkout/js/action/set-shipping-information',
'Magento_Checkout/js/model/step-navigator',
'Magento_Checkout/js/checkout-data'
],
function(
$,
_,
Component,
ko,
customer,
addressList,
addressConverter,
quote,
createShippingAddress,
selectShippingAddress,
shipping,
createBillingAddress,
selectBillingAddress,
setShippingInformationAction,
stepNavigator,
checkoutData
) {
'use strict';
_.extend(shipping.prototype, {
setShippingInformation: function () {
if (this.validateShippingInformation() && this.validateBillingInformation()) {
setShippingInformationAction().done(
function () {
stepNavigator.next();
}
);
}
},
validateBillingInformation: function() {
if($('[name="billing-address-same-as-shipping"]').is(":checked")) {
if (this.isFormInline) {
var shippingAddress = quote.shippingAddress();
var addressData = addressConverter.formAddressDataToQuoteAddress(
this.source.get('shippingAddress')
);
//Copy form data to quote shipping address object
for (var field in addressData) {
if (addressData.hasOwnProperty(field) &&
shippingAddress.hasOwnProperty(field) &&
typeof addressData[field] != 'function' &&
_.isEqual(shippingAddress[field], addressData[field])
) {
shippingAddress[field] = addressData[field];
} else if (typeof addressData[field] != 'function' &&
!_.isEqual(shippingAddress[field], addressData[field])) {
shippingAddress = addressData;
break;
}
}
if (customer.isLoggedIn()) {
shippingAddress.save_in_address_book = 1;
}
var newBillingAddress = createBillingAddress(shippingAddress);
selectBillingAddress(newBillingAddress);
} else {
selectBillingAddress(quote.shippingAddress());
}
return true;
}
var selectedAddress = $('[name="billing_address_id"]').val();
if(selectedAddress) {
var res = addressList.some(function (addressFromList) {
if (selectedAddress == addressFromList.customerAddressId) {
selectBillingAddress(addressFromList);
return true;
}
return false;
});
return res;
}
this.source.set('params.invalid', false);
this.source.trigger('billingAddress.data.validate');
if (this.source.get('params.invalid')) {
return false;
}
var addressData = this.source.get('billingAddress'),
newBillingAddress;
if ($('#billing-save-in-address-book').is(":checked")) {
addressData.save_in_address_book = 1;
}
newBillingAddress = createBillingAddress(addressData);
selectBillingAddress(newBillingAddress);
return true;
}
});
return Component.extend({});
}
);
Download full module from here