Chapters Close

In this post, I’ll guide you through creating a JavaScript Component when working a Magento store, and how to load it on any page you need

Let’s do it

Understanding the JS Components in Magento 2

  1. KnockoutJS component – ‘ko’
    • Checkout page is full of knockout js bindings
  2. jQueryUI component – ‘jquery/ui’
    • Add to cart on the product page & product listing page

Note: You cannot mix both the components code within a single JS component.

Technologies usage

  1. RequireJs
    • It is used for dependency management for all the javascript files
  2. KnockoutJs
    • MVVM pattern using data-bind
  3. jQuery UI Widgets
    • Create stateful jQuery plugins using the same abstraction as all jQuery UI widgets.

First create a custom module

KnockoutJS component

In your module’s web directory, create a simple.js.
Like, app/code/Aureatelabs/JSComponent/view/frontend/web/js/simple.js

define([
        'ko',
        'uiComponent'
    ],
    function(ko, Component) {
        'use strict';
        return Component.extend({
            firstName: ko.observable(''),
            initialize: function() {
                this._super();
            }
        });
    });

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

  1. You can make use of MVVM technique via data-bind & methods of knockoutjs
  2. Assign external HTML template after js component is loaded
  3. Less dependent on jQuery and use of data-bind any elements is recommended.
  4. Changing the HTML template without modifying .PHTML template file.
  5. i18n translation supported
  6. You can set the default options if not given from the frontend
  7. Reusable code
  8. It can contain a list of components in a group like on the checkout page

Disadvantages

  1. Template is rendered after the JS is loaded in the browser and takes time to display.
  2. 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

  1. You can use the jQuery UI Widget to create a component
  2. This component has a constructor function _create to initialize your logic
  3. You can set the default options if not given from the frontend
  4. You can trigger this component from the element itself so you don’t have to rely on the page load using data-mage-init.
  5. Reusable code

Disadvantages

  1. You cannot use the knockout js methods and data-bind here.
  2. 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.

In this article you will be learning about how can use cache-clean.js watcher utility in Magento 2.

The file watcher automatically cleans affected cache types in the Magento 2 cache during development. For example, if you make a change to a template, it only cleans the block_html and full_page caches, not the config or layout caches.

Whole cache flush decrease developer’s performance, so we can use mage2tv/magento-cache-clean

Before starting the installation, we need Node.js version 8.x or above as dependency.

Install For Specific Project

Step 1

Install the node.js, using below command sudo apt-get install nodejs

Confirm node js installation using command node -v

Step 2

Now install mage2tv/magento-cache-clean  for specific project, go at root directory of your project and run below command
composer require --dev mage2tv/magento-cache-clean

Step 3

Confirm cache-clean installation using command vendor/bin/cache-clean.js

If you get the error Error NOSPC on Linux, run the command:

echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

After successfully installation you get output Like:

Release 0.0.42 sponsored by https://www.mage2.tv

Flushing all caches

Usage

In your Magento directory, run vendor/bin/cache-clean.js --watch or -w
Now watch is start, Press Ctrl+C to exit the watcher process.
The file watcher automatically cleans affected cache types, watch will show notification in the terminal about the specific cache clean and recompiles the changes simultaneously.

Hotkeys

When the watcher is running, segments of the cache can be cleaned with individual key press:

KeyCache Segment(s)
cconfig
bblock_html
llayout
ffull_page
a(a for all)
v(V for view) block_html, layout, full_page
ttranslate

There also are hotkeys to clean the static assets in the Adminhtml or the Frontend area or clean the Generated code directory

KeyWork
F Clean Frontend static assets
A Clean Adminhtml static content
G Clean Generated code

Install Globally

Step 1

Now install mage2tv/magento-cache-clean globally run below command
composer global require --dev mage2tv/magento-cache-clean

Step 2

verify where installed it in your pc or system in my case at => home/.config/composer/vendor/bin/cache-clean.js

Step 3

set system path using this command
export PATH="$PATH:$HOME/.config/composer/vendor/bin"

Now the installation process is completed, the next step is to run the cache command.

Step 4

From any project’s root directory you can access using  cache-clean.js

From out-off magento root directory can access using full directory path cache-clean.js -d ./magento230
Here -d or –directory for Magento Base Directory, magento230 is project name

Note: For globally installation can start watch using  cache-clean.js -w or cache-clean.js -d ./magentodirectory -w, For specific installation using vendor/bin/cache-clean.js -w

I hope this comprehensive blog has been helpful. Please leave your comments below, and don’t hesitate to reach out if you require assistance with Magneto store development.

Reference From:

Git Hub: https://github.com/mage2tv/magento-cache-clean/blob/master/readme.md
Mage2tv:https://www.mage2.tv/content/fundamentals/magento-cli-tool/the-magento-cache-clean-js-file-watcher-utility/

In this post, I will be guiding you about symlink in Magento 2.

A symlink or a Symbolic Link is simply enough a shortcut to another file. It is a file that points to another file.

I have attached the below two images for identifying symlinks.

Symlinks are generated in the pub static folder of Magento 2 in developer mode.

Symlinks are generated in the pub static folder of Magento 2 in developer mode.

Common issue faced by Developer when working with knockout Js

In the development stage, when you are working with Js, knockout js and knockout template, the developer faces below issues

  • The changes in knockout js and knockout templates are not affecting on frontend when page load.
  • The developer has to delete the pub static folder or run static content deploy command every time when changes in js and knockout template file.

If you are facing this kind of issue in development, please verify the below steps.

  1. Is the developer mode enabled?
  2. Is symlink is generated in pub static folder or not?
  3. When doing development, open the inspect element in the browser and in the network tab and select the Disable cache checkbox.

1. Is the developer mode enabled?

  • Open the SSH Console and go to the root directory of Magento 2 and run the below command.
bin/magento deploy:mode:show
  • If it is not a developer mode then run below command to enable developer mode.
bin/magento deploy:mode:set developer

In development mode, symlinks are generated automatically when page load.

If you can’t see symlinks in pub static folder even after developer mode enabled. There might be the following reasons.

  • If you have run the static content deploy command in developer mode, it will generate copies instead of symlinks in pub static folder
  • If your web server is Apache then please make sure .htaccess file in pub/static directory otherwise symlinks will not generate.

Notes: When we run static content deploy command in developer mode, it generates copies instead of symlinks in pub static folder So we have to remove that file every time when doing development because symlinks are not created.

Originally, there is no need to run static content deploy command in developer mode. Because on page load it automatically creates symlinks.

Now if copies are generated in pub static folder, perform below steps to generate symlinks.

  • Remove pub static frontend and adminhtml folder(Don’t delete .htaccess file)
rm -rf pub/static/frontend/
rm -rf pub/static/adminhtml/
  • Now load the page, symlinks will create in pub static folder on-demand in developer mode.
  • Install below GitHub module, it will ensure the Magento setup:static-content: deploy will deploy with symlinks instead of copies in Developer mode.

WeareJH / m2-module-symlink-assets

I hope this comprehensive post was helpful. Please leave your comments below, and don’t hesitate to reach out if you require assistance with customizing your Magento store

FAQs

What are symlinks used for?


Symlinks are used to redirect to a different file or folder on your device. Symlink stands for symbolic link which is used in LINUX or UNIX. There are two types of symlinks. Soft links work like shortcuts to a file and directly point to it. Hard links direct you to the file storage.

Is symlink secure?


No, symlinks aren’t secure as they can be manipulated to expose data. Symlinks are prone to attacks that can steal data, change permissions, and corrupt files from unwarranted access. These breaches can be controlled by assigning “create symbolic links” only to trusted admins.

What are the advantages of using a symlink?


The advantages of using symlink are that they can link to both directories and across file systems. They are preferred over hard links as they create links at a namespace level. You can use symlinks to point to any files even if they differ in filesystem, permissions, configurations, and other parameters.

Can you symlink a directory?


Yes, you can symlink a directory. The process is similar to creating a symlink for a file. To create a symlink to a directory, choose a directory to create the link and select a link name. Then, run the command ln -s <target_directory> <link_name>

In this post, I will be guiding you on how to use ViewModels in Magento 2.

Magento 2.2 has done many improvements and one of these is the concept of ViewModels, offloading features from Block classes into separate ViewModel classes.

Why use ViewModels instead of Blocks?

As most of the Block classes that exist in Magento 2 are created by extending upon the \Magento\Framework\View\Element\Template class. Usually, when you create a Block class, you can reuse a lot of functionality from the parent class. But as your class grows in functionality, you might need to insert other dependencies into your Block class. And the way to do that is to override the PHP constructor and add your own dependencies to it. To make sure your parent constructor still works, you need to duplicate all of the parent dependencies and pass them on to the parent like follows:

<?php
namespace Aureatelabs\ModuleName\Block;
class CustomBlock extends \Magento\Framework\View\Element\Template
{
    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }
}

You need to add more code to a PHP constructor, only to satisfy the parent class. If there was no parent class at all, you would not need to add parent dependency like $context or $data to your class in the first place. Inheritance is working against us, making a simple class more complex. We are not maintaining our class only, we are also maintaining the stuff that lives in our parent class.

ViewModels are there to simplify things again. Instead of inserting your dependency in the Block class, you add it to the ViewModel class. And while you would normally reference $block->getSomething() to get the result of that dependency from your class into your template file, you have to use $viewModel->getSomething().

Follow the below steps to use ViewModels in Magento 2.

Here we will be using Aureatelabs as the Vendor name and ModuleName as the name of the module. You can change this according to your Vendor and Module name.

Step 1: Define View Model argument in Block

You can just add an additional XML argument to the Block class, either when creating the block using <block> or when referring to the block using <referenceBlock>. This might look like the following:

<block name="example-view-model" class="Magento\Framework\View\Element\Template" template="Aureatelabs_ModuleName::test.phtml">
    <arguments>
        <argument name="view_model"
                  xsi:type="object">Aureatelabs\ModuleName\ViewModel\Custom</argument>
    </arguments>
</block>

Here we have defined our ViewModel Class Aureatelabs\ModuleName\ViewModel\Custom in the view_model argument of Block.

Since Magento 2.2.1, we don’t even have to specify the class argument on the <block/> node because if class argument not found it will take the default class “Magento\Framework\View\Element\Template”.

Step 2: Define View Model Class

Now we will create a Custom.php in Aureatelabs\ModuleName\ViewModel as we defined in Block.

<?php
namespace Aureatelabs\ModuleName\ViewModel;

use Magento\Framework\View\Element\Block\ArgumentInterface;

class Custom implements ArgumentInterface
{
    public function __construct() {

    }

    public function getSomething()
    {
        return "Hello World";
    }
}

When you use ViewModel class, it must implement Magento\Framework\View\Element\Block\ArgumentInterface.

A constructor does not need to call parent::__construct(), and you can modify the constructor to inject new dependencies as you are used to in other classes.

Step 3: Use ViewModel class in your existing PHTML file

You can insert the new ViewModel class in your existing PHTML template as follows.

<?php
/**@var Aureatelabs\ModuleName\ViewModel\Custom $viewModel*/
$viewModel = $block->getData('view_model');
?>

<?= $viewModel->getSomeThing()?>

ViewModels working in Magento 2.0 or 2.1?

We can use ViewModels in Magento 2.2 and the greater version. But it will not work with Magento 2.0 and 2.1 versions.  Because XSI type Object is not available in Magento 2.0 or 2.1 version.

In short, using ViewModels in Magento 2.0 and  2.1 will give you an error.

FAQs

When to use ViewModel in Magento 2?


You can use ViewModel in Magento 2 to modify, format, or abstract data before using it in a template. ViewModels are good to use when block classes become too complex. With ViewModels, you can keep the templates clean and minimal and also use the block classes to create similar templates.

What is MVVM in Magento 2?


MVVM in Magento 2 stands for Model View ViewModel. It is an architectural system that separates the different development components into three sections: model, view, and ViewModel. The new component, ViewModel, creates true separation between the model and view components, while maintaining a channel between the two. This helps developers write and debug code and simplify web application testing.

Why MVVM is better than MVC?


MVVM is better than MVC because MVVM allows true separation of the model and view layers. This makes it easier to test them as separate units without conflict between different parts of the code which is difficult in MVC. The separation also improves flexibility, allowing developers to utilize a single data set to create multiple ViewModels.

How to override model class in Magento 2?


To override a model class in Magento 2, follow the below-mentioned steps –
1. Create a di.xml file in your module’s etc directory.
2. Define a preference for the original model class using the preference element. 
3. Set the for attribute to the original class name and the type attribute to the new class name.

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
 <preference for="Magento\Customer\Model\Customer" type="Vendor\Module\Model\Rewrite\Customer" />
</config>


4. Create a new class in your module’s Model\Rewrite directory. The class should extend the original class and should have the same name as the new class name defined in the di.xml file.

<?php
namespace Vendor\Module\Model\Rewrite;
class Customer extends \Magento\Customer\Model\Customer
{
 // Your custom methods here
}


5. Refresh the cache and run the setup:upgrade command.

Magento theme structure

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.

<theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd">
     <title>New Theme</title>
     <parent>Magento/luma</parent>
     <media>
         <preview_image>media/preview.jpg</preview_image>
     </media>
</theme>

view.xml file

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.

<view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/view.xsd">
<media>
<images module="Magento_Catalog">
…
     <image id="category_page_grid" type="small_image">
        <width>250</width>
        <height>250</height>
      </image>
...
    </images>
</media>
</view>

Module and theme layout files

Base layouts:

Layout files provided by modules. Location :
– Page configuration and generic layout files: <module_dir>/view/frontend/layout
– Page layout files: <module_dir>/view/frontend/page_layout

Theme layouts:

Layout files provided by themes. Location :
– Page configuration and generic layout files: <theme_dir>/<Namespace>_<Module>/layout
– Page layout files: <theme_dir>/<Namespace>_<Module>/page_layout

Best practice: Do not modify base design files instead of follow coding standards and extend or override a layout for any modification.

Extend Layout

You can create extending layout files, and modify your code as per your needs. To extend the layout, add layout file at the following location:

<theme_dir>/<Namespace_Module>/layout/layout.xml

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:

<theme_dir>/<Namespace_Module>/layout/override/base/layout.xml

For example,
/Magento_Checkout/layout/override/base/checkout_cart_index.xml

Override theme layouts

To override theme layout file, put a layout file with same name at the following location:

<theme_dir>/<Namespace_Module>/layout/override/theme/<Parent_Vendor>/<Parent_Theme>/layout.xml

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.

Example:

<move element="name.of.an.element" destination="name.of.destination.element" as="new_alias" before="-"/>

Remove block and container using remove and display attribute of <referenceBlock> / <referenceContainer> element.

  • You can remove block or container from layout by setting value of remove attribute to true, default value of remove attribute is false.

Example:

<referenceBlock name="block.name" remove="true" />
  • <remove> is used to remove static resources linked in a page from the <head> section.

Example:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
   <head>
        <!-- Remove local resources -->
        <remove src="css/styles-m.css" />
        <!-- Remove external resources -->
        <remove src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"/>
        <remove src="http://fonts.googleapis.com/css?family=Montserrat" /> 
   </head>
</page>
  • 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.

Example:

<referenceContainer name="container.name" display="false" />

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 files in <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:

@import '_buttons_extend.less';

Override component’s styles

Create _button.less file in <theme_dir>/web/css/source directory. And add your custom style of button in it.

Magento Ui Component Files are located at lib/web/css directory:

You can also include your own custom CSS by adding it in default_head_blocks.xml file which is located in the Magento_Theme module.

Example

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <css src="css/styles-m.css" />
        <css src="css/styles-l.css" media="screen and (min-width: 768px)"/>
        <css src="css/print.css" media="print" />
    </head>
</page>

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: 

  1. Module translations: <module_dir>/i18n/
  2. Theme translations:
    • <parent_theme_dir>/i18n/ (iterated through all ancestor themes)
    • <current_theme_dir>/i18n/
  3. Translation package: app/i18n/
  4. Magento database

As we all know there are many cases in Magento 2 development where the product listing is too big which affects page load time. Now you can decrease the page load time by adding that specific block to the cache. Below are the different ways to achieve your goal:

Add a block to cache from layout xml:

Add below _construct() in your respected block file and specify cache_lifetime and a unique cache_tags cache identifier.

{{block name="explore-color-section" class="Companyname\Packagename\Block\Product\CustomProductCollection" product_id="51,52,53,54,55,56,57,58,59,60,40, 41, 42, 43, 44, 45, 46, 47, 70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90 ,91,92,93,94,95,96,97,98,99,100,101,102,103" cacheable="true" cache_lifetime="86400" template="Magento_Theme::html/explore_color_code.phtml"}}

Add a block to cache from block file:

Add the _construct () given below in your respected block file and specify cache_lifetime and a unique cache_tags cache identifier.

/**
     * {@inheritdoc}
     */
    protected function _construct()
    {
        parent::_construct();
        $this->addData([
            'cache_lifetime' => 86400,
            'cache_tags' => ["explore_your_colors_ilnp"]]);
    }

Note: Here its _construct not __construct

Add a block having pagination to cache(Ex. Product listing with pagination):

Add the  _construct() given below in your respected block file and specify cache_lifetime and a unique cache_tags cache identifier.

 protected function _construct()
    {
        parent::_construct();
        $this->addData([
                'cache_lifetime' => 86400,
                'cache_tags' => [\Magento\Store\Model\Store::CACHE_TAG, \Magento\Cms\Model\Block::CACHE_TAG],
                'cache_key'  => "explore_your_colors_ilnp_".$this->request->getPost('page_number')
            ]
        );
    }

Lastly, run the command given below to make changes effective:

php bin/magento cache:clean
php bin/magento cache:flush

Related resources:

In this article, we will see how to implement a payment method rendering in Magento 2 checkout.

Step 1: Create the .js component file

It is important to note that you will be implementing the payment method renderer as a UI component. You should not overwrite the default Magento code, just add your customizations code in a separate module. Create the component’s .js file (the payment method renderer) in your custom module directory. It must be stored in the <your_module_dir>/view/frontend/web/js/view/ directory.

The general view of the payment method renderer is as follows:

define(
   [
       'Magento_Checkout/js/view/payment/default'
   ],
   function (Component) {
       'use strict';
       return Component.extend({
           defaults: {
               template: '%path to template%'
           },
           // add required logic here
       });
   }
)

Step 2: Create the .js component registering the renderer

In your custom module directory, create the .js UI component which registers the payment method renderer in the renderers list. It must be located under the <your_module_dir>/view/frontend/web/js/view/ directory.

define(
   [
       'uiComponent',
       'Magento_Checkout/js/model/payment/renderer-list'
   ],
   function (
       Component,
       rendererList
   ) {
       'use strict';
       rendererList.push(
           {
               type: '%payment_method_code%',
               component: '%js_renderer_component%'
           },
           // other payment method renderers if required
       );
       /** Add view logic here if needed */
       return Component.extend({});
   }
);

Step 3: Create the template for the payment method component

Create a new <your_module_dir>/view/frontend/web/template/<your_template>.html file in your custom module directory. The template can use Knockout JS syntax.

Step 4: Declare the payment method in layout

<your_module_dir>/view/frontend/layout/checkout_index_index.xml
  • file in your custom module directory.
  • Add the code given below to that file.
<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="billing-step" xsi:type="array">
                                       <item name="component" xsi:type="string">uiComponent</item>
                                       <item name="children" xsi:type="array">
                                           <item name="payment" xsi:type="array">
                                               <item name="children" xsi:type="array">
                                                   <!-- Declare additional before payment components. START -->
                                                   <item name="beforeMethods" xsi:type="array">
                                                       <item name="component" xsi:type="string">uiComponent</item>
                                                       <item name="displayArea" xsi:type="string">beforeMethods</item>
                                                       <item name="children" xsi:type="array">
                                                           <item name="%your_feature_name%" xsi:type="array">
                                                               <item name="component" xsi:type="string">%path/to/your/feature_js_component%</item>
                                                           </item>
                                                       </item>
                                                   </item>
                                                   <!-- Declare additional before payment components. END -->
                                                   <!-- Declare the payment method (the component that registrates in the list). START -->
                                                   <item name="renders" xsi:type="array">
                                                       <item name="children" xsi:type="array">
                                                           <item name="%group name of the payment methods%" xsi:type="array">
                                                               <!-- Example of value: Magento_Authorizenet/js/view/payment/authorizenet-->
                                                               <item name="component" xsi:type="string">%component_that_registers_payment_renderer%</item>
                                                               <item name="methods" xsi:type="array">

                                                                   <!-- Add this if your payment method requires entering a billing address-->
                                                                   <item name="%payment_method_code%" xsi:type="array">
                                                                       <item name="isBillingAddressRequired" xsi:type="boolean">true</item>
                                                                   </item>
                                                               </item>
                                                           </item>
                                                       </item>
                                                       <!-- Declare the payment method (the component that registrates in the list). END -->
                                                       <!-- Declare additional after payment components. START -->
                                                       <item name="afterMethods" xsi:type="array">
                                                           <item name="component" xsi:type="string">uiComponent</item>
                                                           <item name="displayArea" xsi:type="string">afterMethods</item>
                                                           <item name="children" xsi:type="array">
                                                               <item name="%your_feature_name%" xsi:type="array">
                                                                   <item name="component" xsi:type="string">%path/to/your/feature_js_component%</item>
                                                               </item>
                                                           </item>
                                                       </item>
                                                       <!-- Declare additional after payment components. END -->
                                                   </item>
                                               </item>
                                           </item>
                                       </item>
                                   </item>
                               </item>
                           </item>
                       </item>
                   </item>
               </item>
           </argument>
       </arguments>
   </referenceBlock>
</body>
</page>

FAQs

How do you add a custom field in checkout page below payment method in Magento 2?


To add a custom field in checkout page below payment method in Magento 2, follow the below steps:
1. Add the custom field to the table.
2. Add a checkbox below the payment method.
3. Save it in the quote table and sales order table.
4. Display the attribute on the admin side.

How to configure payment methods in Magento 2?


To configure payment methods in Magento 2, you need to go to Stores>Configuration through the admin panel. Click on the Sales>Payment Methods tab to find all default payment methods. Click on a payment method, such as bank transfer or money order, to configure the title, instructions, and order value.

How to customize Magento 2 checkout page?


To customize Magento 2 checkout page, follow these steps:
1. Add new checkout components by coding the view part of the component.
2. Add the component to the existing checkout page layout.
3. Customize the component by changing its .js implementation.
4. You can add, customize, or manage these checkout steps through the Magento 2 admin dashboard.

How to add custom form in checkout page in Magento 2?


To add a custom form in the checkout page in Magento 2, follow the below steps.
1. Create a JavaScript implementation for the new form.
2. Create an HTML template for the UI component.
3. Declare the region where the form is to be inserted in the checkout page.
4. Clear the cache and test the implementation.

When you are setting up a Shopping Cart Price Rule in Magento, you can choose a base condition on which the rule will apply on the subtotal. There are instances when the merchants may want to base the conditions on the final price, or the price that includes the subtraction of any other discounts applied. The code below shows how to add a grand total condition in Magento, which in this case will be a combination of the subtotal plus any discount applied.

A merchant may wish to set up the rule for the subtotal with the discount instead of the subtotal in case if they encounter any of the  scenarios given below:

  1. The merchant has an existing Shopping Cart Price Rule (Discount1), that provides a flat £10 discount off of the whole cart (no coupon code) if the customers’ subtotal is equal or greater than £100.
  2. The merchant also has an another Shopping Cart Price Rule (Discount2), that provides another flat £10 discount off of the whole cart, but requires a coupon code. This code will be applied if the customers’ subtotal is is equal or greater than £100.
  3. The customer adds a product that costs £100 and goes to the cart page.
  4. Discount1 has been applied automatically as the customer has met the criteria.
  5. The customer correctly enters in the coupon code from Discount2, and they receive another £10 discount, despite the subtotal staying at £100. The merchant may want the coupon code to only apply to the grand total, which because of Discount1, has dropped to £90.

#Magento 2

1. In your module, Ex:Companyname_Packagename, Create a di.xml file on the <root>/app/code/Companyname/Packagename/etc folder.

<type name="Magento\SalesRule\Model\Rule\Condition\Address">
        <plugin name="load-attribute-options" type="Companyname\Packagename\Plugin\Address" />
</type>

2. Now create a Address.php file at location <root>/app/code/Companyname/Packagename/Plugin folder.

<?php
namespace Companyname\Packagename\Plugin;

class Address
{
        public function afterLoadAttributeOptions(\Magento\SalesRule\Model\Rule\Condition\Address $subject)
    {
        $attributes = $subject->getAttributeOption();
        $attributes['base_subtotal_with_discount'] = __('Subtotal With Discount');
        $subject->setAttributeOption($attributes);
        return $subject;
    }

     public function afterGetInputType(\Magento\SalesRule\Model\Rule\Condition\Address $subject)
    {
        switch ($subject->getAttribute()) {
            case 'base_subtotal':
            case 'base_subtotal_with_discount':
            case 'weight':
            case 'total_qty':
                return 'numeric';

            case 'shipping_method':
            case 'payment_method':
            case 'country_id':
            case 'region_id':
                return 'select';
        }

        return 'string';
    }
}

3. Now execute the command given below in order to see the effective changes:

php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy en_US -f
php bin/magento cache:clean
php bin/magento cache:flush

4. The result will be as follows:

#Magento 1

<p>1. In your module, Ex:<code>Companyname_Packagename</code>, Create a <code>config.xml</code> file on the <code>/app/code/Companyname/Packagename/etc</code> folder.</p>

2. Now create Address.php file at location <root>/app/code/Companyname/Packagename/Model/SalesRule/Rule/Condition folder.

3. Assuming you’ve set up your module correctly, you should notice that the Subtotal With Discount option has been successfully added to the Conditions dropdown menu, and will be available for use if you wish to apply the rules that include a combination of subtotal along with the discounts.

4. That’s it, fellas! Here it goes:

In this post, I will be guiding you to enable Two-Factor Authentication (2FA) in Magento 2.3.x version.

The advantage of 2FA:

  1. Higher security to your Magento 2 Admin
  2. Lower down the risk of the data breach.
  3. Give your store more values.

Let’s do it

Introduction

A User friendly two factor authentication was invented and patent by Indian origin: BHASKAR RAGHAV [IN] and KUNAL SHARMA [IN] for the Google Authenticator app. It is the most accepted concept today. Many mobile apps and websites are using it.

TOTP or time base one-time password is used by Google Authenticator that keeps changing the password every 30 seconds. Two users can’t have the same passwords and it is generated randomly.

2FA extension comes pre-installed by the latest Magento 2.3 is built by the MSP team. It is necessary that everyone must enable this out-of-box feature in the M2 Webstore and other login accounts.

How to

Register device with the Magento 2FA login

  • Login to your Magento 2 Store admin
  • On left hand side, click on Stores > Configuration link
  • On the configuration page, browse to the SECURITY > 2FA.
  • Enable the 2FA service of the one of the providers you frequently use. Like I have enabled Google Authenticator.
  • To force all users to use 2FA you must uncheck the “Use system value” of Force providers field and select the Google Authenticator.
  • After I have enabled the 2FA of Google Authenticator then admin will be logout and QR code scan page will be required to register your device.
  • Next step is to scan the above QR code from the Google Authenticator app and provide the 6 digit code in this form then click the Confirm button.
  • On success I will be redirected to the Magento 2 Admin dashboard page.
  • Now my device is registered for 2FA and feels safer now.

Login admin after Magento 2FA setup

  • When you visit the Admin login, you will be asked for username & password.
  • After the login success, you will be asked for the 6 digit number password from the Google Authenticator app.
  • Submit the correct 2FA code & you are logged in the Magento 2 admin.
  • Now you can do your admin things.

Multiple Factor Authentication Setup in 2FA

Surprisingly you can assign users their 2FA app preferences like Google Authenticator, Duo Security, Authy and U2F Devices (Yubikey and others).

Note: For this “Force providers” must check(✔) the “use system value” in the 2FA configuration page.

For that here is the real-world use case:

User Authenticator provider
Main admin Google Authenticator
Shipper Authy
Inventory users Duo Security
Managers and Marketing users U2F USB Authentication device

Disabled the 2FA code in the emergency

  • You can disable the 2FA by below command:
    php bin/magento msp:security:tfa:disable
  • Once you have deployed, tested or done admin operations then you re-enable the 2FA from the admin.

Advantages

  1. Your store is more secure from the hackers who are trying to steal sensitive data.
  2. Only 1 admin account can be shared with multiple users so you have full control over data.
  3. You can assign multiple authentication providers for each user.
  4. Before the 2FA login, an admin account shared the login details with multiple users and if anyone made changes to the data then it was not possible to identify.

Disadvantages

  1. 1 extra step is required to pass for Admin access
  2. You cannot share your admin details to users like developers working remotely. So have to create a new user for them.

    We hope you found this article insightful. Feel free to drop your comments below, and contact us for any help needed in developing the Magento store.
Table of Contents

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. 

var config = {
   "map": {
       "*": {
           "menu": "js/menu-custom"
       }
   }
};

Step 3

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.

Thank you for reading this article. Your feedback is welcome in the comments section, and we’re available to assist with anything related to Magento development.

Grow your online business like 3,081 subscribers

    * This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
    envelope

    Thank You!

    We are reviewing your submission, and will be in touch shortly.