1

Magento 2 Shipping address selection changes to drop down form radio options. I want to display default shipping address on page load but it's always showing first shipping address as a selected. In Magento_Checkout/template/shipping-address/list.html :

<div class="field addresses">
    <div class="control">
        <div class="shipping-address-items">
            <select class="select" name="billing_address_id" data-bind="
        options: shippingAddressOptions,
        optionsText: shippingAddressOptionsText,
        value: selectedShippingAddress,
        selectedOptions: chosenCountries,
        event: {change: onShippingAddressChange(selectedShippingAddress())};
    "></select>
        </div>
    </div>
</div>

In js/view/shipping.js file:

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/model/shipping-rates-validator',
    'Magento_Checkout/js/model/shipping-address/form-popup-state',
    'Magento_Checkout/js/model/shipping-service',
    'Magento_Checkout/js/action/select-shipping-method',
    'Magento_Checkout/js/model/shipping-rate-registry',
    'Magento_Checkout/js/action/set-shipping-information',
    'Magento_Checkout/js/model/step-navigator',
    'Magento_Ui/js/modal/modal',
    'Magento_Checkout/js/model/checkout-data-resolver',
    'Magento_Checkout/js/checkout-data',
    'uiRegistry',
    'Magento_Catalog/js/price-utils',
    'mage/translate',        
    'Magento_Checkout/js/model/shipping-rate-service'
],
function(
    $,
    _,
    Component,
    ko,
    customer,
    addressList,
    addressConverter,
    quote,
    createShippingAddress,
    selectShippingAddress,
    shippingRatesValidator,
    formPopUpState,
    shippingService,
    selectShippingMethodAction,
    rateRegistry,
    setShippingInformationAction,
    stepNavigator,
    modal,
    checkoutDataResolver,
    checkoutData,
    registry,
    priceUtils,
    $t
) {
    'use strict';
    var popUp = null,
    shippingAddress = quote.shippingAddress,
    newAddressOption = {
            getAddressInline: function () {
            return $t('New Address');
        },
            customerAddressId: null
        },
        shippingAddressOptions = addressList().filter(function (address) {
            return address.getType() == 'customer-address';
        });

    shippingAddressOptions.push(newAddressOption);
    return Component.extend(
        {
            defaults: {
                template: 'Magento_Checkout/shipping'
            },
            visible: ko.observable(!quote.isVirtual()),
            errorValidationMessage: ko.observable(false),
            isCustomerLoggedIn: customer.isLoggedIn,
            isFormPopUpVisible: formPopUpState.isVisible,
            isFormInline: addressList().length == 0,
            isNewAddressAdded: ko.observable(false),
            saveInAddressBook: 1,
            quoteIsVirtual: quote.isVirtual(),
            shippingAddressOptions: shippingAddressOptions,
            chosenCountries:ko.observableArray([shippingAddress]),
0

I have to change data-bind funtion to

optionsAfterRender: function(option, item) { if(){ selectedShippingAddress(item); } }

keep your backup file before any changes. Complete solutions: It worked for my requirement. You may do some change according to your requirement. But using this we can change shipping address list to drop down.

Add custom address template name : Magento_Checkout/shipping-address/mylist.html

<!-- ko if: (visible)-->
<div class="field addresses">
<div class="control">
    <div class="shipping-address-items">
        <select class="select" name="billing_address_id" data-bind="
    options: shippingAddressOptions,
    optionsText: shippingAddressOptionsText,
    value: selectedShippingAddress,
    optionsAfterRender: function(option, item) {
    if(item.customerAddressId==Object.entries(quoteShippingAddress)[2][1].customerAddressId) {
    selectedShippingAddress(item);
     }
    },
    event: {change: onShippingAddressChange(selectedShippingAddress())};
"></select>
    </div>
</div>

Change and add mylist.html file in shipping.html file.

    <!-- ko if: (!quoteIsVirtual) -->
        <!-- ko foreach: getRegion('customer-email') -->
            <!-- ko template: getTemplate() --><!-- /ko -->
        <!--/ko-->
    <!--/ko-->

   <!-- ko foreach: getRegion('before-form') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
    <!--/ko-->


    <!-- Address form pop up -->

        <div id="opc-new-shipping-address" data-bind="visible: isShippingAddressFormVisible()">
       <!-- ko template: 'Magento_Checkout/shipping-address/form' --><!-- /ko -->
    </div>
        <div class="actions-toolbar">
        <div class="primary">
            <button class="action action-update" type="button" data-bind="click: updateShippingAddress">
                <span data-bind="i18n: 'Update'"></span>
            </button>
            <!-- <button class="action action-cancel" type="button" data-bind="click: cancelAddressEdit"> 
             <span data-bind="i18n: 'Cancel'"></span>
            </button> -->
        </div>
        </div>
   </div>
 </li>
 <!-- Shipping method template -->
 <li id="opc-shipping_method"
class="checkout-shipping-method"
data-bind="fadeVisible: visible(), blockLoader: isLoading"
role="presentation">
<div class="checkout-shipping-method">
    <div class="step-title" data-bind="i18n: 'Shipping Method'" data-role="title"></div>
    <!-- ko foreach: getRegion('before-shipping-method-form') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
    <!-- /ko -->
    <div id="checkout-step-shipping_method"
         class="step-content"
         data-role="content"
         role="tabpanel"
         aria-hidden="false">
        <!-- ko if: rates().length  -->
        <form class="form methods-shipping" id="co-shipping-method-form" data-bind="submit: setShippingInformation" novalidate="novalidate">
            <div id="checkout-shipping-method-load">
                  <table class="table-checkout-shipping-method">
                    <thead>
                        <tr class="row">
                            <th class="col col-method" data-bind="i18n: 'Select Method'"></th>
                            <th class="col col-method" data-bind="i18n: 'Method Title'"></th>
                            <th class="col col-price" data-bind="i18n: 'Price'"></th>                                
                 <!-- <th class="col col-carrier" data-bind="i18n: 'Carrier Title'"></th> -->
                        </tr>
                    </thead>
                    <tbody>

                    <!-- ko foreach: { data: rates(), as: 'method'}-->
                    <tr class="row" data-bind="click: $parent.selectShippingMethod">
                        <td class="col col-method">
                            <!-- ko ifnot: method.error_message -->
                            <!-- ko if: $parent.rates().length == 1 -->
                  <input class="radio"
                                   type="radio"
                                   data-bind="attr: {
                                                checked: $parent.rates().length == 1,
                                                'value' : method.carrier_code + '_' + method.method_code,
                                                'id': 's_method_' + method.method_code,
                                                'aria-labelledby': 'label_method_' + method.method_code + '_' + method.carrier_code + ' ' + 'label_carrier_' + method.method_code + '_' + method.carrier_code
                                             }" />
                            <!-- /ko -->
                            <!--ko ifnot: ($parent.rates().length == 1)-->
                            <input type="radio"
                                   data-bind="
                                            value: method.carrier_code + '_' + method.method_code,
                                            checked: $parent.isSelected,
                                            attr: {
                                                'id': 's_method_' + method.carrier_code + '_' + method.method_code,
                                                'aria-labelledby': 'label_method_' + method.method_code + '_' + method.carrier_code + ' ' + 'label_carrier_' + method.method_code + '_' + method.carrier_code
                                            },
                                            click: $parent.selectShippingMethod"
                                   class="radio"/>
                            <!--/ko-->
                            <!-- /ko -->
                        </td>

                        <td class="col col-method"
                                data-bind="text: method.method_title, attr: {'id': 'label_method_' + method.method_code + '_' + method.carrier_code}"></td>   


                        <!-- <td class="col col-carrier"
                                data-bind="text: method.carrier_title, attr: {'id': 'label_carrier_' + method.method_code + '_' + method.carrier_code}"></td> -->

                        <td class="col col-price">
                            <!-- ko foreach: $parent.getRegion('price') -->
                            <!-- ko template: getTemplate() --><!-- /ko -->
                            <!-- /ko -->
                        </td>         


                    </tr>

                    <!-- ko if:  method.error_message -->
                    <tr class="row row-error">
                        <td class="col col-error" colspan="4">
                            <div class="message error">
                                <div data-bind="text: method.error_message"></div>
                            </div>
                            <span class="no-display">
                                <input type="radio" data-bind="attr: {'value' : method.method_code, 'id': 's_method_' + method.method_code}"/>
                            </span>
                        </td>
                    </tr>
                    <!-- /ko -->

                    <!-- /ko -->
                    </tbody>
                </table>
            </div>
            <div id="onepage-checkout-shipping-method-additional-load">
                <!-- ko foreach: getRegion('shippingAdditional') -->
                <!-- ko template: getTemplate() --><!-- /ko -->
                <!-- /ko -->
            </div>
            <!-- ko if: errorValidationMessage().length > 0 -->
            <div class="message notice">
                <span><!-- ko text: errorValidationMessage()--><!-- /ko --></span>
            </div>
            <!-- /ko -->
           <!-- <div class="actions-toolbar" id="shipping-method-buttons-container">
                <div class="primary">
        <button data-role="opc-continue" type="submit" class="button action continue primary">-->
        <!--<span>&lt;!&ndash; ko i18n: 'Next'&ndash;&gt;&lt;!&ndash; /ko &ndash;&gt;</span>-->
                 <!--   </button>
                </div>
            </div> -->
        </form>
        <!-- /ko -->
        <!-- ko ifnot: rates().length > 0 --><div class="no-quotes-block"><!-- ko i18n: 'Sorry, no quotes are available for this order at this time'--><!-- /ko --></div><!-- /ko -->
    </div>
</div>

Now add Shipping.js file.

 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/model/shipping-rates-validator',
    'Magento_Checkout/js/model/shipping-address/form-popup-state',
    'Magento_Checkout/js/model/shipping-service',
    'Magento_Checkout/js/action/select-shipping-method',
    'Magento_Checkout/js/model/shipping-rate-registry',
    'Magento_Checkout/js/action/set-shipping-information',
    'Magento_Checkout/js/model/step-navigator',
    'Magento_Ui/js/modal/modal',
    'Magento_Checkout/js/model/checkout-data-resolver',
    'Magento_Checkout/js/checkout-data',
    'uiRegistry',
    'Magento_Catalog/js/price-utils',
    'mage/translate',
    'Magento_Checkout/js/model/shipping-rate-service'
],
function(
    $,
    _,
    Component,
    ko,
    customer,
    addressList,
    addressConverter,
    quote,
    createShippingAddress,
    selectShippingAddress,
    shippingRatesValidator,
    formPopUpState,
    shippingService,
    selectShippingMethodAction,
    rateRegistry,
    setShippingInformationAction,
    stepNavigator,
    modal,
    checkoutDataResolver,
    checkoutData,
    registry,
    priceUtils,
    $t
) {
    'use strict';
    var popUp = null,
    newAddressOption = {
            getAddressInline: function () {
            return $t('New Address');
        },
            customerAddressId: null
        },
        shippingAddressOptions = addressList().filter(function (address) {
            return address.getType() == 'customer-address';
        });

    shippingAddressOptions.push(newAddressOption);
    return Component.extend(
        {
            defaults: {
                template: 'Magento_Checkout/shipping'
            },
            visible: ko.observable(!quote.isVirtual()),
            errorValidationMessage: ko.observable(false),
            isCustomerLoggedIn: customer.isLoggedIn,
            isFormPopUpVisible: formPopUpState.isVisible,
            isFormInline: addressList().length == 0,
            isNewAddressAdded: ko.observable(false),
            saveInAddressBook: 1,
            quoteIsVirtual: quote.isVirtual(),
            shippingAddressOptions: shippingAddressOptions,
            initialize: function () {
                var self = this;
                this._super()
                .observe({
                    selectedShippingAddress: null,
                    isShippingAddressFormVisible: !customer.isLoggedIn() || shippingAddressOptions.length == 1
                });
                 if (!quote.isVirtual()) {
                     stepNavigator.registerStep(
                         'payment',
                         '',
                         'Review & Payments',
                         this.visible, _.bind(this.navigate, this),
                         10
                     );
                 }

                checkoutDataResolver.resolveShippingAddress();

                var hasNewAddress = addressList.some(
                    function (address) {
                        return address.getType() == 'new-customer-address';
                    }
                );

                this.isNewAddressAdded(hasNewAddress);

                this.isFormPopUpVisible.subscribe(
                    function (value) {
                        if (value) {
                            self.getPopUp().openModal();
                        }
                    }
                );

                quote.shippingMethod.subscribe(
                    function (value) {
                        self.errorValidationMessage(false);
                    }
                );

                registry.async('checkoutProvider')(function (checkoutProvider) {
                    var shippingAddressData = checkoutData.getShippingAddressFromData();
                    if (shippingAddressData) {
                        checkoutProvider.set(
                            'shippingAddress',
                            $.extend({}, checkoutProvider.get('shippingAddress'), shippingAddressData)
                        );
                    }
                    checkoutProvider.on(
                        'shippingAddress', function (shippingAddressData) {
                            checkoutData.setShippingAddressFromData(shippingAddressData);
                        }
                    );
                });

                this.rates.subscribe(
                    function (grates) {
                        self.shippingRateGroups([]);
                        _.each(
                            grates, function (rate) {
                                var carrierTitle = rate['carrier_title'];

                                if (self.shippingRateGroups.indexOf(carrierTitle) === -1) {
                                    self.shippingRateGroups.push(carrierTitle);
                                }
                            }
                        );
                    }
                );

                return this;
            },

            navigate: function () {
                //load data from server for shipping step
            },

            shippingAddressOptionsText: function (address) {
            return address.getAddressInline();
            },
            onShippingAddressChange: function (address) {
                this.isShippingAddressFormVisible(address == newAddressOption);
            },
            updateShippingAddress: function () {
            if (this.selectedShippingAddress() && this.selectedShippingAddress() != newAddressOption) {
                selectShippingAddress(this.selectedShippingAddress());
                checkoutData.setSelectedShippingAddress(this.selectedShippingAddress().getKey());
              //  this.isShippingMethodFormVisible(true);
            } else {
              this.source.set('params.invalid', false);
                this.source.trigger('shippingAddress.data.validate');

                if (!this.source.get('params.invalid')) {
                    var addressData = this.source.get('shippingAddress');
                  // if user clicked the checkbox, its value is true or false. Need to convert.
                    addressData.save_in_address_book = this.saveInAddressBook ? 1 : 0;

                    // New address must be selected as a shipping address
                    var newShippingAddress = createShippingAddress(addressData);
                    selectShippingAddress(newShippingAddress);
                    checkoutData.setSelectedShippingAddress(newShippingAddress.getKey());
                    checkoutData.setNewCustomerShippingAddress(addressData);
                    //this.isShippingMethodFormVisible(true);
                    }
                }
            },

            initElement: function(element) {
                if (element.index === 'shipping-address-fieldset') {
                    shippingRatesValidator.bindChangeHandlers(element.elems(), false);
                }
            },

            getPopUp: function() {
                var self = this;
                if (!popUp) {
                    var buttons = this.popUpForm.options.buttons;
                    this.popUpForm.options.buttons = [
                    {
                        text: buttons.save.text ? buttons.save.text : $t('Save Address'),
                        class: buttons.save.class ? buttons.save.class : 'action primary action-save-address',
                        click: self.saveNewAddress.bind(self)
                    },
                    {
                        text: buttons.cancel.text ? buttons.cancel.text: $t('Cancel'),
                        class: buttons.cancel.class ? buttons.cancel.class : 'action secondary action-hide-popup',
                        click: function() {
                            this.closeModal();
                        }
                    }
                    ];
                    this.popUpForm.options.closed = function() {
                        self.isFormPopUpVisible(false);
                    };
                    popUp = modal(this.popUpForm.options, $(this.popUpForm.element));
                }
                return popUp;
            },

            /**
        * Show address form popup
        */
            showFormPopUp: function() {
                this.isFormPopUpVisible(true);
            },


            /**
        * Save new shipping address
        */
            saveNewAddress: function() {
                this.source.set('params.invalid', false);
                this.source.trigger('shippingAddress.data.validate');

                if (!this.source.get('params.invalid')) {
                    var addressData = this.source.get('shippingAddress');
         // if user clicked the checkbox, its value is true or false. Need to convert.
                    addressData.save_in_address_book = this.saveInAddressBook ? 1 : 0;

                    // New address must be selected as a shipping address
                    var newShippingAddress = createShippingAddress(addressData);
                    selectShippingAddress(newShippingAddress);
                    checkoutData.setSelectedShippingAddress(newShippingAddress.getKey());
                    checkoutData.setNewCustomerShippingAddress(addressData);
                    this.getPopUp().closeModal();
                    this.isNewAddressAdded(true);
                }
            },

            /**
        * Shipping Method View
        **/
            rates: shippingService.getShippingRates(),
            shippingRateGroups: ko.observableArray([]),
            isLoading: shippingService.isLoading,
            isSelected: ko.computed(
                function () {

                    return quote.shippingMethod() ? quote.shippingMethod().carrier_code + '_' + quote.shippingMethod().method_code : null;
                }
            ),

            getFormattedPrice: function (price) {
                return priceUtils.formatPrice(price, quote.getPriceFormat());
            },

            getRatesForGroup: function (shippingRateGroupTitle) {
                return _.filter(
                    this.rates(), function (rate) {
                        return shippingRateGroupTitle === rate['carrier_title'];
                    }
                );
            },

            selectShippingMethod: function(shippingMethod) {
                selectShippingMethodAction(shippingMethod);
                checkoutData.setSelectedShippingRate(shippingMethod.carrier_code + '_' + shippingMethod.method_code);
                $('#co-shipping-method-form').submit();
                return true;
            },

            selectVirtualMethod: function(shippingMethod) {
                var flagg = true;
                var METHOD_SEPARATOR = ':';
                var SEPARATOR = '~';
                var rates = new Array();
                var sortedrate = new Array();
                jQuery('.vendor-rates').each(
                    function(indx,elm){
                        var flag = false;
                        jQuery(elm).find('.radio').each(
                            function(i,inpt){
                                if(inpt.checked) {
                                    flag = true;
                                    rates.push(inpt.value);
                                }
                            }
                        );
                        if(!flag) {
                            flagg = false;
                        }
                    }
                );
                if(flagg) {
                    for(var i = 0; i < rates.length; i ++){
                        var sortedValue = rates[i].split(SEPARATOR);
                        var pos = isNaN(parseInt(sortedValue[1])) ? 0 : parseInt(sortedValue[1]);
                        sortedrate[pos] = rates[i];
                    }
                    var rate = '';
                    for(var i=0;i< sortedrate.length;i++){
                        if(sortedrate[i]!=undefined) {
                            if(rate) {
                                rate = rate + METHOD_SEPARATOR + sortedrate[i];
                            }else{
                                rate =  sortedrate[i];
                            }
                        }
                    }
                    if(document.getElementById('s_method_vendor_rates_'+rate)) {
                        var event = new Event('click');
                        document.getElementById('s_method_vendor_rates_'+rate).dispatchEvent(event);
                    }
                }
                return true;
            },

            setShippingInformation: function () {
                if (this.validateShippingInformation()) {
                    setShippingInformationAction().done(
                        function() {
                           // stepNavigator.next();
                        }
                    );
                }
            },

            validateShippingInformation: function () {
                var shippingAddress,
                addressData,
                loginFormSelector = 'form[data-role=email-with-possible-login]',
                emailValidationResult = customer.isLoggedIn();

                if (!quote.shippingMethod()) {
                    this.errorValidationMessage('Please specify a shipping method.');
                    return false;
                }

                if (!customer.isLoggedIn()) {
                    $(loginFormSelector).validation();
                    emailValidationResult = Boolean($(loginFormSelector + ' input[name=username]').valid());
                }

                if (!emailValidationResult) {
                    $(loginFormSelector + ' input[name=username]').focus();
                }

                if (this.isFormInline) {
                    this.source.set('params.invalid', false);
                    this.source.trigger('shippingAddress.data.validate');
                    if (this.source.get('shippingAddress.custom_attributes')) {
                        this.source.trigger('shippingAddress.custom_attributes.data.validate');
                    };
                    if (this.source.get('params.invalid')
                        || !quote.shippingMethod().method_code
                        || !quote.shippingMethod().carrier_code
                        || !emailValidationResult
                    ) {
                        return false;
                    }
                    shippingAddress = quote.shippingAddress();
                    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'
                        ) {
                            shippingAddress[field] = addressData[field];
                        }
                    }

                    if (customer.isLoggedIn()) {
                        shippingAddress.save_in_address_book = 1;
                    }
                    selectShippingAddress(shippingAddress);
                }
                return true;
            }
        }
    );
}
);
| improve this answer | |
  • Can we get the full solution to this? After some testing, it doesn't appear that this solution is complete – elfling Apr 8 '19 at 15:28
  • can u please give full solution for this? – Ram Sampathi Jun 5 '19 at 14:43
  • @elfling are u got answer for this? – Ram Sampathi Jun 7 '19 at 6:50
  • Sort of - I've postponed it, but if we could pull resources magento.stackexchange.com/questions/267340/… – elfling Jun 7 '19 at 8:18
  • @RamSampathi I update my answer. – Shekhar Suman Jun 7 '19 at 8:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.