In this post, I will be guiding you to excluding JavaScript files from minifying. Sometimes it is required to load third-party JavaScript files in our custom module/theme & .min file is not available.
Use Case
You are implementing a custom payment method module for the current project:
Here you found the payment gateway is providing minified javascript file(s) but file(s) name doesn’t have .min suffix like payment-abc.min.js
At this point, you have a tight budget and ETA. You can’t just tell the client or payment gateway refused your request.
How minify js files work in Magento 2?
At first, you have to enable minify JavaScript JS from Admin or using the command line in production mode.
Now open the Magento 2 website on the browser and open DevTools, in Network panel it will show the minify js loader file: requirejs-min-resolver.min.js. This file is responsible to open all js files in .min and contains RegEx rules to exclude js files from adding .min suffix. Magento creates this file when JS minify & production mode is enabled.
Let’s do it
Using the above test case:
You are implementing a custom payment method module for the current project but JavaScript files of the payment gateway do not have .min suffix and you will tell Magento 2 to add file path in the requirejs-min-resolver.min.js file.
We will add an after plugin on the getExcludes method of Magento\Framework\View\Asset\Minification class. So you got an idea this class is responsible for minifying files in Magento 2.
In your di.xml file at app/code/Vendor/Payment/etc directory:
<?php
namespace Vendor\PaymentModule\Plugin\View;
use \Magento\Framework\View\Asset\Minification;
class MinificationPlugin
{
/**
* Exclude static componentry files from being minified.
*
* Using the config node `minify_exclude` is not an option because it does
* not get merged but overridden by subsequent modules.
*
* @see \Magento\Framework\View\Asset\Minification::XML_PATH_MINIFICATION_EXCLUDES
*
* @param Minification $subject
* @param string[] $excludes
* @param string $contentType
* @return string[]
*/
public function afterGetExcludes(Minification $subject, array $excludes, $contentType)
{
// Here we are checking if not “js” then skip it
if ($contentType !== 'js') {
return $excludes; // Skip if contentType is not “js”
}
// Array variable adds path to exclude minify
$excludes[]= 'https://webservices.paymentgateway.net/';
return $excludes;
}
}
Now change the Vendor/PaymentModule name as per your module and then run below commands:
In browser, now check the payment js will open properly because file path is added in requirejs-min-resolver.min.js file.
Conclusion
Excluding JS files from minifying is an out-of-box feature of Magento 2 and it is very helpful when working with third-party services like Google ReCaptcha, Payment methods, shipping methods, email marketing, etc.
Let me know if you found the article helpful so that it will encourage me to write new blogs.
A Helper is a class that provides functionalities for various features throughout the Magento website. Available for use anywhere on the website, Magento 2 Helper can be called in controllers, views, models and even in other helpers too!
Here, I will show you how to call a helper class methods in the template files. There’s a small tip for you, we suggest you use the second method.
Method 1: Using $this->helper directly in the template files
In Magento 2 templates there is an object: $this. It is an object of the class. Check below how to call the helper method using $this.
Use this method as a last resort because as far as we know, calling a helper in your template is equal to using the object manager directly. Thus, we should inject the helper in the constructor of the block. See method 2 given below.
Method 2: By injecting helper in the constructor of the block class
This is the best practice for using helper in Magento 2. Helper method can be called anywhere in Magento 2 using Dependency Injection. You should not call the helper directly in the template.
To use this helper method, check the below code snippet where you can see the helper instance is dependent on the block, that renders the template and creates a method in your block, which then calls the helper and calls that method in the template.
protected $helper;
public function __construct(
....
\{Vendor}\{Module}\Helper\Data $helper,
....
) {
....
$this->helper = $helper;
....
}
public function callHelperMethod()
{
return $this->helper->getDataFromHelper();
}
Then you can call the helper in your template with : $block->callHelperMethod()
Conclusion
In this article, I’ve shown you how to call the helper method in .phtml template files. If you still need any help regarding the helper class or Magento, we are happy to help you. Feel free to get in touch!
FAQs
What is template helper code?
Template helper code is the code used to build dynamic templates which are used to simplify HTML tasks. They are included as part of another template code to improve the functionality of the template. There are various helper codes depending on the function such as tag helpers, link helpers, etc.
What is built in helpers?
Built in helpers are helpers already included in the template engine. They are universally available to any developers using the template and usually simplify commonly used functions such as looping or formatting. Some of the commonly used built-in helpers include #if, #unless, #each, #with, and others.
How to use helper in magento2?
To use helper in Magento 2, add the newly created module in a Helper folder. Update the module directory to include the folder. Then, create a data.php file in the Helper folder and update the file with the required code. Edit the index.php file and clear cache to check the helper.
How to call Phtml in Magento 2?
To call phtml in Magento 2, you need to use block code. First, login to the admin dashboard and write the block code in the content of any CMS page. After deploying the code, the phtml appears on the CMS page. You can also call phtml on all CMS pages by using a layout file.
Create a simple.phtml file in the frontend or CMS block and add below content:
<div data-bind="scope: 'component-name'">First name:
<div><input type="text" data-bind="textInput: firstName" /></div>
</div>
<p>Notes: Magento_Ui/js/core/app - this js is responsible for binding Knockout JS components with the DOM elements then you can use ko methods. Scope attribute - it is used to chain the JS and the HTML DOM together using the knockoutjs. Component-name - Must be unique on the current page. It can be any meaningful word and could be js file name. Use same name used in the</p>
Advantages
You can make use of MVVM technique via data-bind & methods of knockoutjs
Assign external HTML template after js component is loaded
Less dependent on jQuery and use of data-bind any elements is recommended.
Changing the HTML template without modifying .PHTML template file.
i18n translation supported
You can set the default options if not given from the frontend
Reusable code
It can contain a list of components in a group like on the checkout page
Disadvantages
Template is rendered after the JS is loaded in the browser and takes time to display.
External html template is already loaded then the new version will be loaded from the browser cache.
jQuery UI component
This method is used to add events to the HTML element when the JS component is loaded. Here you don’t cannot use the scope binding. While your JS component will get the DOM element object to implement the logic on it.How to use data-mage-init attribute is used to bind the HTML DOM with the JS component. simple2.js
define([
'jquery',
'jquery/ui'
], function($) {
'use strict';
$.widget('mage.simple2', { // component name = simple2
options: {
text: null,
displayEle: null
},
/**
* Bind handlers to events
*/
_create: function() {
console.info(this.options); // print the options in console
// Save options to the element for later
this.element.data('options', this.options);
// Add event and method to the element
this._on({
'keyup': $.proxy(this._method, this.element)
});
},
_method: function() {
// fetch the element options
var options = this.data('options');
$(options.displayEle).text(this.val());
}
});
return $.mage.simple2; // return simple2 component
});
Then in your HTML template file use like the below:
<div>
<h2>Simple2 demo</h2>
<label> Name: <input type="text" data-mage-init="{"Aureatelabs_Simple2/js/simple2": { "text": "to-send-in-the-js-file", "displayEle": "#text"} }" /> </label>
<h2>Your text here: <small></small></h2>
</div>
<p>Notes: You can use the alias from the requirejs-config(1) or use the full path of the js file(2): For example: 1. RequireJS alias: <input type="text" data-mage-init="{"simple2": { "text": "to-send-in-the-js-file", "displayEle": "#text"} }" /> 2. RequireJS full path: <input type="text" data-mage-init="{"Aureatelabs_Simple2/js/simple2": { "text": "to-send-in-the-js-file", "displayEle": "#text"} }" /> 3. The data json inside the simple2 object is optional so you can use the empty object like: {} I.e. { "text": "to-send-in-the-js-file", "displayEle": "#text"}</p>
You will see the jQueryUI component:
Advantages
You can use the jQuery UI Widget to create a component
This component has a constructor function _create to initialize your logic
You can set the default options if not given from the frontend
You can trigger this component from the element itself so you don’t have to rely on the page load using data-mage-init.
Reusable code
Disadvantages
You cannot use the knockout js methods and data-bind here.
You cannot use it in the checkout layout customizations.
FAQs
Which JavaScript component is used in magento 2?
The JavaScript component used in Magento 2 is a package of JavaScript libraries & frameworks to build a powerful and flexible front end. These are jQuery, Knockout.js, RequireJS, LESS (CSS preprocessor), UI Widgets, and reusable UI elements. Along with creating custom themes, modules, and features, they dramatically increase page speed and seamlessly handle JS dependency.
How do I merge CSS and js in Magento 2?
To merge CSS and JS in Magento 2, follow the below-mentioned steps –
For CSS: 1. Log in to your Admin Panel and go to Stores —> Settings —> Configuration. 2. Navigate the left panel and expand Developers. 3. Next, select CSS Settings and expand the options. 4. Further, go to Merge CSS Files and set Yes from the dropdown list. 5. Thereafter, click on Save Config.
For JS: 1. Repeat the first two steps mentioned above. 2. Now, select JavaScript Settings and expand the options. 3. Next, go to Merge JavaScript Files and set Yes from the dropdown list. 4. Then, click on Save Config.
How to add custom js in checkout page magento 2?
To add custom JS to the checkout page in Magento 2, follow the below-mentioned steps – 1. Create a web directory in the root of your custom module, and inside it, create a js directory. 2. Now, place your custom JS file inside this js directory. 3. Next, create a requirejs-config.js file in the root of your custom module. 4. Inside the above file, define the path of your custom JS file 5. Further, create a layout XML file in your custom module as app/code/Vendor/Module/view/frontend/layout/checkout_index_index.xml. 6. Inside the above file, add the following code to include the custom JS file for the checkout page: <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <head> <script src="Vendor_Module::js/checkout_custom.js"/> </head> </page> 7. Thereafter, run the command php bin/magento setup:static-content:deploy and clear the cache.
How do you add the JS and CSS files into a custom module in magento 2?
To add the JS and CSS into a custom module in Magento 2, follow the below-mentioned steps – 1. Create a web directory in the root of your custom module, and inside it, create two directories: js and css. 2. Place your JS and CSS files inside their respective directories. 3. Create a requirejs-config.js file in the root of your custom module. 4. Define the path of your JS and CSS files 5. Include the JS and CSS files in specific layout/page. 6. Run the command static-content:deploy to enable changes.
Storefront custom themes are located at the app/design/frontend/<Vendor>/ directory.
Magento built-in themes are located at the vendor/magento/theme-frontend-<theme_code> directory when magento is installed using composer.
The structure of a Magento theme directory
theme.xml file
Create theme.xml file to initialize the theme. It contains theme title, the preview image of theme, parent theme from which all layouts, CSS can be inherited by default.
To set parent theme is one of the best practices if you want to inherit default Magento theme and customize it.
There are unlimited levels of parent theme that you can inherit, and they will fall back sequentially until there are no more parents defined.
Create view.xml file to change the type and size of the image or create your own type in the app/design/frontend/<VendorName>/<ThemeName>/etc directory.
For example, To customize the layout defined in /view/frontend/layout/catalog_product_view.xml, you need to add a layout file with the same name in your custom theme, like the following: /Magento_Catalog/layout/catalog_product_view.xml
Override Layout
If you want to change a large amount of customization, you have to override layout file, This means that the new file that you place in the theme will be used instead of the parent theme layout file of the base layout file.
Override base layouts
To override base layout file, put a layout file with same name at the following location:
For example, /Magento_Checkout/layout/override/theme/Magento/luma/checkout_cart_index.xml
Do not remove generic blocks from *.phtml files or xml layouts.
If you may have deleted generic blocks from XML layouts, some extensions won’t work. Magento third party extension makes use of the generic block to insert its own new block, if you remove a generic block, there’s a possibility that the third party extension won’t work properly.
Containers and blocks
A container is a structure without content which holds other blocks and containers.
<move> element is used to change the position of block or container, to move an element, you have to refer it with its name and then set destination attribute which can either be a container or a block.
You can disable a block or a container with its child element from the layout by setting the value of display attribute to a true, default value of display attribute is false. You can always overwrite the display attribute, but in case if the remove attribute is set to true, the value of the display attribute is ignored.
You can reorder block and container using after and before attributes of the <referenceBlock> / <referenceContainer> element.
both after and before attributes are present, after attribute takes precedence.
both after and before attributes are absent or empty, all elements are considered as non-positioned. All other elements are positioned at their specified locations.
multiple elements have before or after set to dash (-), all elements are displayed at the top (or bottom in case of after attribute).but the ordering of these elements is undefined.
CSS
When the theme is inherited from the parent theme, make changes in _extend.less or _theme.less file instead of overriding the .less files.
Your theme’s _theme.less file overrides your parent’s theme. So, if you have assign parent theme to your theme, copy the entire content from the parent theme’s _theme.less file.
Use Magento generic CSS classes wherever possible.
There are many CSS classes, that are defined in Magento default installation, whenever you are going to create new store template, it is a good practice to use generic CSS classes because there are many third-party extensions that uses Magento generic CSS classes.
Override or extend Magento Ui library component
To customize UI component, you can override or extend the Magento library components.
For Example, if you want to change the style of a button, you can extend or override _button.less file.
Extend component’s styles
Add _buttons_extend.less and _extend.less filesin <theme_dir>/web/css/source directory. Then add your custom style of button in _buttons_extend.less file, and register it in the _extend.less file by adding the following code:
If you want to make major customization in the existing style of a particular module, copy _module.less file from Magento core module to your own theme in the same path, and add your customization to it.
Translation
If you need to change the phrases in the user interface, add custom CSV dictionary files instead of overriding .phtml templates.
In case if the location is changed for a store, Magento searches for translations in the related dictionaries at the following location:
Module translations: <module_dir>/i18n/
Theme translations:
<parent_theme_dir>/i18n/ (iterated through all ancestor themes)
This article will help you to understand how to extend an existing jquery widget in Magento 2. Sometimes, there may arise situations where a project requires specific/custom approach, in that case, developers need to modify the default logic.
Let’s take an example where we will make certain changes to the main navigation javascript part.
The chief file responsible for the functioning of the navigation menu is menu.js located at [project_root]/lib/web/mage/ with other default js system components.
Now, if you want to extend or overwrite it, you’ll have to make sure that you follow the steps given below:
Step 1
To properly extend the parts of menu.js with our custom content, the first step is to map our js file so that the system loads it instead of the default file.
Magento uses equirejs-config.js files to successfully map js components on the system. The first thing that matters is to understand where to place requirejs-config.js. It can be placed at several levels.
We will create a file that will replace the menu.js file. Let’s call it menu-custom.js and place it under [our theme]/web/js/ directory.
Step 2
Next, we will have to create the requirejs-config.js file and place it under [our theme]/root directory. This will help us to map our file so as to replace the default one.
We will extend default functionality and for this, we will be using the jQuery widget factory. We will place the following code in our newly created menu-custom.js file.
define([
'jquery',
'jquery/ui',
'mage/menu'],
function($){
$.widget('kiwicommerce.menu', $.mage.menu, {
_init: function () {
console.log("This message is from menu-custom.js");
},
toggle: function () {
console.log("This message is from menu-custom.js");
}
});
return $.kiwicommerce.menu;
});
Our custom widget instance called kiwicommerce.menu is extending default $.mage.menu and in this example, we will be extending two methods, that are _init and toggle. Toggle method is in charge of toggle navigation on mobile phones while the _init method is in charge of the component initialization.
Here we can add our custom logic as needed. Currently, we have added a simple console message for testing.
After following the example given above you will see that the link must have been added in the top menu and will appear as given below:
Now, Let’s learn to add link into top header section instead of top link dropdown. In this example, we will add “Contact Us” link in header. For that you need to add the following code in default.xml file.
In the above example we have used delimiter block (name with “customer-account-navigation-delimiter-demo”) to add a separator. In case you don’t want the separator, remove that block.
In this post, I will be guiding you on how to add non-category link to the navigation menu in Magento 2.
If you still think that the container navigation.sections which holds the category links it can be referenced and passing following arguments can create a new category link under navigation menu, you are highly mistaken.
In this post, I will be guiding you on how to use private content or sections in Magento 2.
Since private content is specific to individual users, it’s reasonable to handle it on the client side i.e. web browser.
A section is a piece of customer data grouped together. Each section is represented by the key that is used to access and manage data itself.
Magento loads sections by AJAX request to /customer/section/load/ and caches loaded data in the browser local storage under the key mage-cache-storage. Magento tracks when some section is changed and load updated section automatically.
Here we will be using Aureatelabs as the Vendor name and CustomSection as the name of the module. You can change this according to your Vendor and Module name.
Follow the below steps to define the custom section and use the data of the custom section in our custom phtml file.
Step 1: Define a custom section
We will define a custom section in the di.xml file by adding a new section into sections pool.
Create di.xml file in app/code/Aureatelabs/CustomSection/etc/frontend directory.
<?php
namespace Aureatelabs\CustomSection\CustomerData;
use Magento\Customer\CustomerData\SectionSourceInterface;
class CustomSection implements SectionSourceInterface
{
public function getSectionData()
{
return [
'customdata' => "We are getting data from custom section",
];
}
}
In getSectionData() method we will define our data that we want to store in section.
Step 2: Display custom section data in frontend
We will display our custom section data in the product view page. You can get section data in any Magento pages.
Next, we will create catalog_product_view.xml in app/code/Aureatelabs/CustomSection/view/frontend/layout directory.
You can see custom section data in browser local storage.
In the section.js file, we have used Magento_Customer/js/customer-data as this Magento js library file is responsible for set section data and get section data. Section data gets updated when ajax call with the post, put, delete requests are made.
Additional Information
When caching is enabled the whole page content is cached so sections help us to dynamically manage the components of the page.
For example, the complete page is cached, Now when the customer logs in or logs out only the components get updated with the value from the section as you can see the customer name, cart, wish list are all managed by section.
All sections data are fetched in one single ajax call, hence the number of ajax requests are reduced to a huge number.
Magento assumes that section data is changed when a customer sends some state modification request (POST, PUT, DELETE). To minimize the load on the server, developers should specify which action (or request) updates which customer data section in etc/frontend/sections.xml.
You can refer Magento/Catalog/etc/frontend/sections.xml file.
In the section.xml file, they have defined update the compare-products section when one of these actions catalog/product_compare/add, catalog/product_compare/remove, catalog/product_compare/clear are requested.
If the action name is * that means that section will be updated on each POST and PUT request. If the section tag is missed then all sections will be updated.
You can refer Magento/Theme/etc/frontend/sections.xml file.
Here we have added customerData.reload('custom_section'); to reload section data whenever we refresh the page.
FAQs
What is private content in Magento 2?
Private content in Magento 2 is data accessible only to a particular user, based on the configurational changes made by them. This can be anything from purchase history to payment information. Magento 2 uses customer-data.js library to check if a customer is logged in, and then sends server requests to reload only a part of the data without refreshing the entire page cache.
How do I override layout XML in Magento 2?
To override layout XML in Magento 2, create a folder structure with the same name in themes as present in view/frontend. Then, change the etc/module.xml file and replace it by the new file created. You can do this by placing the file in app/design/frontend/[Vendor]/[Theme_Name]/Vendor_ModuleName/layout/some_layout.xml
Where is config xml in Magento?
The config.xml in Magento is located in the DOMAIN_HOME/config directory. The servers get their configuration data from these files. Each server has its own configuration file in the domain which can be accessed through <module_folder>/etc/adminhtml/system.xml. The config.xml files are used to set specific values for the configuration of the system.
How to use section XML in Magento 2?
To use section XML in Magento 2, create a new layout XML file in the app/code/[VendorName]/[ModuleName]/view/frontend/layout directory. Then, refresh the cache and view any product page to view section data. In Magento 2, sections define the layout configuration for different store areas, such as the header, footer, and content.
In this Magento web development hack, we will be guiding you on how to add custom phtml in the admin product ui-component form in the Magento 2.
Here we will be using Aureatelabs as the Vendor name and CustomTab as the name of the module. You can change this according to your Vendor and Module name.
To start with, we will create a custom tab in the product admin form after which we will call our custom block and phtml file inside our custom tab.
Step 1: Create Product_form.xml file
For this, you have to create a product_form.xml file in app/code/Aureatelabs/CustomTab/view/adminhtml/ui_component directory