Today, we will talk about the checkout part again. It seems to be one of the most difficult parts in Magento 2. Lately, I have had a task where I needed to change the width of the payment step as compared to the shipping step. The payment step should be wider than the shipping step. In order to do it, I had to somehow recognise on which step the user currently is. In order to do that, I had to add a class which will tell us where we are. However, it is not as easy as it sounds.
I am happy to share with you all the necessary code that you will need to add to your project. I will provide you with an example and I will focus on a case where we want to recognise shipping and payment step in checkout on frontend in Magento 2 project. If you need any help, book with me 1hr Magento 2 Frontend consultation or learn more about starting work with Magento 2!
Let’s start with the plan of what we need to do in order to recognise shipping and payment steps in checkout on frontend in our Magento 2 project. The only thing we want to do is to add class to certain steps. In my case, I will add the class “checkout-shipping-step” to the body of the shipping step and the class “checkout-payment-step” to the body of the payment step.
SUBSCRIBE TO MAGENTO 2 NEWSLETTER!
Would you like to get information when new Magento tutorial is available?
Subscribe to the newsletter and be up to date!
In our case, we will need to work only with javascript files. We will need to extend the step-navigator.js file and add our code into the getActiveItemIndex method. Let’s start by extending the file.
We will use Javascript Mixins as we want to add new methods to the class and augment the behaviour of the base the class by adding different mixins to it.
It is really important to add this file into the correct place. It should be added to vendor/vendor-name/module-name/view/frontend/ or vendor/vendor-name/theme-name/module-name/ or vendor/vendor-name/theme-name/ where “vendor-name“, “theme-name” and “module-name” needs to be replaced with your name of vendor, theme and module name. If you are not creating a new module, you can follow the second example and use the Magento_Checkout module in your theme for this case, as we make an implementation into the checkout part. Another solution would be to follow the third example and add files directly into your theme.
Whichever solution you will choose, requirejs-config.js needs to be in the root folder of the module, theme or theme module. As soon as you choose one way, you need to follow it.
Let’s say we will add our file to vendor/vendor-name/module-name/view/frontend/ or vendor/vendor-name/theme-name/module-name/, our file should look like as below:
var config = { config: { mixins: { 'Magento_Checkout/js/model/step-navigator': { 'Vendor_Module/js/model/step-navigator-mixin': true } } } };
In case, you decide to choose the last solution vendor/vendor-name/theme-name/, your file should look like the following:
var config = { config: { mixins: { 'Magento_Checkout/js/model/step-navigator': { 'js/model/step-navigator-mixin': true } } } };
At this point, we will add our new file step-navigator-mixin.js. The new file will be added to vendor/vendor-name/module-name/view/frontend/web/js/ or vendor/vendor-name/theme-name/module-name/web/js/ or vendor/vendor-name/theme-name/web/js/ where “vendor-name“, “theme-name” and “module-name” needs to be replaced with your name of vendor, theme and module name. If you are not creating a new module, you can follow the second example and use the Magento_Checkout module in your theme for this case, as we make an implementation into the checkout part. Another solution would be to follow the third example and add files directly into your theme. Your decision depends on where you have added the requirejs-config.js file.
define([ 'jquery', 'mage/utils/wrapper' ], function ($, wrapper) { 'use strict'; return function(stepNavigator){ var customGetActiveItemIndex = wrapper.wrap(stepNavigator.getActiveItemIndex, function(originalGetActiveItemIndex){ var activeIndex = originalGetActiveItemIndex(), body = $('body'), shippingClass = 'checkout-shipping-step', paymentClass = 'checkout-payment-step'; if (activeIndex){ body.removeClass(shippingClass); body.addClass(paymentClass); } else { body.removeClass(paymentClass); body.addClass(shippingClass); } return activeIndex; }); stepNavigator.getActiveItemIndex = customGetActiveItemIndex; return stepNavigator; }; });
Let’s analyse this code to understand what each part means. I also really often struggle to understand which part of the code or names I can change for my custom ones and which I need to keep as an example, all of it I will try to explain right now. I have been following JavaScript mixins Magento 2 documentation where I wanted to add a mixin module that extends the target
component with new functions. However, this documentation didn’t help so much. The biggest help was The Curious Case of Magento 2 Mixins where I found examples that are much closer to my case. Let’s go through parts of this code.
'jquery', 'mage/utils/wrapper'
We need to link “jquery” and “wrapper” references to be able use these modules in our code. The point of the wrapper module is to wrap an existing function call with a new code, without needing to edit the original function.
$, wrapper
$ is related to “jquery” and “wrapper” is related to “made/utils/wrapper“, you can use here any other names, but in this specific order.
stepNavigator
This is our alias for the Magento function which we will wrap. It can be any name, so no worries about it. Just keep it the same in all the marked parts.
customGetActiveItemIndex
This is the custom name for our new function. Again, you can use your custom name.
stepNavigator.getActiveItemIndex
This is the method of the wrapped function which we want to extend. getActiveItemIndex
returns 0 when we are on the shipping step and 1 when we are on the payment step.
originalGetActiveItemIndex
This is our alias for the method which we want to extend. You can use your custom name at this point.
In general we use a wrapper module with a wrap function to wrap the original function with our new function and to extend certain methods.
var activeIndex = originalGetActiveItemIndex()
At this point we run the originalgetActiveItemIndex
and get a value which it returns, based on this value we add our custom code, where we decide which class we should add to our body.
return activeIndex;
At the end, we return the value which the original method returns.
stepNavigator.getActiveItemIndex = customGetActiveItemIndex
Here we assign our new method to the original method.
return stepNavigator;
And it is really the end when we return the whole function that was wrapped. That’s it!
I took for you some screenshots of our implementations based on the Luma theme. I have not added any styling so this is how it will be displayed by default. As you can see, I recognise shipping and payment step in checkout on frontend in my Magento 2 project.
I hope it can help with your journey with M2! Also feel free to give your feedback and advices. In case I made a mistake, let me know! I am only human being ?
Did you find this post useful? I would be more than happy if you share it with your friends, maybe someone else will find it useful as well. Good luck!
Editor – Natasha Jay O’Neil, please contact Natasha directly for queries related to her services.
Zaneta loves challenges so deciding about career path she has chosen typical male industry. Woman who codes. Every 1-2 years she lives in different part of the world. Gym dates is something what she specialised in. Healthy lifestyle, extreme sports and motorbikes have stolen her hear years ago.
Morning reading, reading itself, was never my strong side. I really didn't like reading so…
A good road trip is all about planning and execution, ensuring you know which locations…
Ok, let me make it straight. I have never been a morning person. I remember…
Years ago if someone would tell me that I am going to meditate I would…
The US is perhaps the world’s greatest transcontinental civilisation. It stretches all the way from…
Let’s talk a little bit about workout clothing. Let me make it clear, I am…