preloder

Customizing a tooltip template to allow HTML content in Magento 2

Prev Next

I’ve been looking for a way to put HTML content into a tooltip for one of the checkout shipping form fields in Magento 2. The native tooltip.html template does not allow to use a template, and I decided to customize it.

My goal is to get additional styling features inside the tooltip, so when a customer clicks on a question mark the tooltip content is styled with additional markup.

Problem

The close look into the tooltip.html template will give us a hint that the content for the tooltip will always be unstyled and HTML is no allowed there. The tooltip.html template file from the vendor/magento/module-ui/view/frontend/web/templates/form/element/helper directory.


<div class="field-tooltip toggle">
    <!-- ko if: (tooltip.link)-->
    <a class="field-tooltip-action action-help" target="_blank" data-toggle="dropdown" data-bind="attr: {href: tooltip.link}, mageInit: {'dropdown':{'activeClass': '_active'}}"></a>
     <!-- /ko -->

     <!-- ko if: (!tooltip.link)-->
     <span class="field-tooltip-action action-help" tabindex="0" data-toggle="dropdown" data-bind="mageInit: {'dropdown':{'activeClass': '_active'}}"></span>
     <!-- /ko -->

    <div class="field-tooltip-content" data-target="dropdown" text="tooltip.description"></div>
</div>

The text=”tooltip.description” allows only text provided in the description.

Solution

In order to provide an HTML version of the tooltip content, we have to override the tooltip.html template. In the custom tooltip.html template the text argument should be replaced with html argument, so all the HTML will be passed and interpreted. A user will see the nicely styled tooltip.

The last div should be changed in the custom tooltip.html template as below:

<div class="field-tooltip-content" data-target="dropdown" html="tooltip.description">
</div>

Please note the html=”tooltip.description” part which is a key in our solution. As a result, the custom template should be the following:

<div class="field-tooltip toggle">
    <!-- ko if: (tooltip.link)-->
    <a class="field-tooltip-action action-help"
       target="_blank"
       data-toggle="dropdown"
       data-bind="attr: {href: tooltip.link}, mageInit: {'dropdown':{'activeClass': '_active'}}"></a>
     <!-- /ko -->

     <!-- ko if: (!tooltip.link)-->
     <span class="field-tooltip-action action-help"
        tabindex="0"
        data-toggle="dropdown"
        data-bind="mageInit: {'dropdown':{'activeClass': '_active'}}"></span>
     <!-- /ko -->

    <div class="field-tooltip-content"
         data-target="dropdown" html="tooltip.description">
    </div>
</div>

The next step is to pass the custom tooltip.html template name into the configuration of the field which should show the tooltip. As for this example, I am going to use the _countryid field from a shipping form on the Magento 2 checkout. There are two ways on how we can provide custom configuration for checkout fields in Magento 2. First one is to use checkout_index_index.xml configuration file, the second approach is a Plugin class for the Magento\Checkout\Block\Checkout\LayoutProcessor class. I will show you the Plugin option.

The Layout Processor Plugin

The plugin is responsible for reading the jsLayout configuration and providing the custom configuration into the _countryid field. The good reason to use the plugin is that billing forms can’t be customized via the checkout_index_index.xml file as each billing form can be rendered in the scope of a more than one payment method. That said, it is a great idea to have one customization in one place instead of having multiple sources. That is why I use the plugin for customizing the _countryid field.

The Pronko\Tooltip\Plugin\LayoutProcessor class has the afterProcess method, so the layout configuration passed via the $jsLayout has been processed and ready to be rendered on a front-end. The afterProcess method should look like the following:

public function afterProcess(LayoutProcessor $subject, array $jsLayout)
{
    $fields = &$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
        ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'];

    $fields = array_replace_recursive($fields, $this->getFieldsConfig());

    return $jsLayout;
}

The private method getFieldsConfig provides additional configuration for the _countryid field. In the future, we may want to add more customizations to the getFieldsConfig method. The getFieldsConfig method:

    private function getFieldsConfig()
    {
        return [
            'country_id' => [
                'config' => [
                    'tooltipTpl' => 'Pronko_Tooltip/form/element/helper/tooltip',
                    'tooltip' => [
                        'description' => "<b>Custom text:</b> text <br /> <p>Line two</p>",
                    ]
                ]
            ]
        ];
    }

There are two pieces of the additional configuration have been passed into the _countryid field. The tooltipTpl holds the path to the custom tooltip.html template. The template should be located under the /view/frontend/web/template/form/element/helper/tooltip.html file.

The description is the HTML content of the tooltip which is rendered as a content of the country_id tooltip on the front-end.

As you may develop your own implementation of the tooltip, you may want to load the description content via CMS block or configuration which is usually stored in a database. This is outside of this blog post.

Make sure to check the spelling of the tooltipTpl key as it is the different naming convention for the elementTmpl. Don’t be confused with this.

As a result, the Pronko\Tooltip\Plugin\LayoutProcessor class should look like the following.

<?php

namespace Pronko\Tooltip\Plugin;

use Magento\Checkout\Block\Checkout\LayoutProcessor;

/**
 * Class AddressLayoutProcessor
 */
class AddressLayoutProcessor
{
    /**
     * @param LayoutProcessor $subject
     * @param array $jsLayout
     * @return array
     */
    public function afterProcess(LayoutProcessor $subject, array $jsLayout)
    {
        $fields = &$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
        ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'];

        $fields = array_replace_recursive($fields, $this->getFieldsConfig());

        return $jsLayout;
    }

    /**
     * @return array
     */
    private function getFieldsConfig()
    {
        return [
            'country_id' => [
                'config' => [
                    'tooltipTpl' => 'Pronko_Tooltip/form/element/helper/tooltip',
                    'tooltip' => [
                        'description' => "<b>Custom text:</b> text <br /> <p>Line two</p>",
                    ]
                ]
            ]
        ];
    }
}

In case you are new to Magento 2 and want to build the custom module from the very beginning and include this code into your custom module, I recommend to watch the video How to create my first Magento 2 module.

The Conclusion

Interestingly that I’ve spend a good few hours looking for a proper solution and enable HTML content into a tooltip for Magento 2 checkout. Obviously, this is a good improvement for Magento 2, and I have to create a Pull Request and contribute to Magento 2. Anyway, this is it. Looking forward for your comments and feedback.

Max with his team of Magento enthusiasts won the Best Magento 1 to Magento 2 Migration Award at the Magento Imagine 2017. As CEO at Pronko Consulting, he is actively working with Magento 2, delivering superior customer experience. As one of the most famous developers on a market and in the Magento Community, he launched Magento 2 blog, Magento DevChannel – YouTube channel in 2017 where he shares his knowledge, experience and the best practices in the Magento field.

Posted on Jun 17, 2018

The Devletter

Subscribe to my Magento 2 tips and tutorials content.
Every week I send an interesting email directly to your inbox

Related Posts

Show
Hide
Pre-order the Magento 2 payment integration course TODAY PRE-ORDER
Hello. Add your message here.