Magento 2 Product Quick View

Related Inchoo Services

What I’m about to share is still somewhat experimental, so it might be wise to test it and adjust according to your needs before you add it to production.

Those who doesn’t want to read whole article, can access extension directly on github here.

Everyone else, continue reading!

Sometimes we want to preview product directly from the category page, but unfortunately that can’t be done by default, so I created simple extension for it.
Basic idea is to add “Quick view” button on product box on category listing which when clicked will open modal window showing the product with all its functionality usually available only on product view page.

Getting started

Create app/code/Inchoo/QuickView/registration.php and add this code:

<?php
/**
 * @category    Inchoo
 * @package     Inchoo_QuickView
 */
 
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Inchoo_QuickView',
    __DIR__
);

We need this to register our new module.

Let’s also create app/code/Inchoo/QuickView/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Inchoo_QuickView" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Catalog"/>
            <module name="Magento_Customer"/>
        </sequence>
    </module>
</config>

and app/code/Inchoo/QuickView/composer.json

{
  "name": "inchoo/module-quickview",
  "description": "N/A",
  "require": {
    "php": "~5.6.0|~7.0.0",
    "magento/framework": "100.1.*"
  },
  "type": "magento2-module",
  "version": "1.0.0",
  "license": [
    "proprietary"
  ],
  "autoload": {
    "files": [
      "registration.php"
    ],
    "psr-4": {
      "Inchoo\\QuickView\\": ""
    }
  }
}

 

At this point you should be able to enable this module simply by running:

php bin/magento module:enable Inchoo_QuickView

Adding some functionality

This is where it becomes more interesting…
Let’s first add quick view button on every product box in the category page.
I’m not really into frontend atm, so sorry for not being well designed 🙂
Anyway,
Create app/code/Inchoo/QuickView/view/frontend/layout/catalog_category_view.xml inside your project and add this:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <referenceBlock name="category.product.addto">
                <block class="Magento\Catalog\Block\Product\ProductList\Item\Block"
                       name="category.product.quickview"
                       as="quickview"
                       template="Inchoo_QuickView::product/productlist/item/quickview.phtml"/>
            </referenceBlock>
        </referenceContainer>
    </body>
</page>

This will add button near “Add to cart” button. Style it way you want.

Before we get into JavaScript which will make most of functionality (as you probably expected), note this…
Once we load product page in modal window, last thing we need is to look exactly like on product view page.
You will probably need to remove some elements via XML.
In order to be able to do that, let’s override Magento\Catalog\Controller\Product\View and add new handle in case we call product via iframe.
Hold my beer…
Create app/code/Inchoo/QuickView/etc/frontend/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
 
    <preference for="Magento\Catalog\Controller\Product\View"
                type="Inchoo\QuickView\Controller\Product\View" />
</config>

That’s it, now we need app/code/Inchoo/QuickView/Controller/Product/View.php

<?php
 
namespace Inchoo\QuickView\Controller\Product;
 
use Magento\Catalog\Controller\Product\View as CatalogView;
 
/**
 * Class View
 *
 * @package Inchoo\QuickView\Controller\Product
 */
class View extends CatalogView
{
    /**
     * Overriden in order to add new layout handle in case product page is loaded in iframe
     *
     * @return \Magento\Framework\Controller\Result\Forward|\Magento\Framework\Controller\Result\Redirect
     */
    public function execute()
    {
        if ($this->getRequest()->getParam("iframe")) {
            $layout = $this->_view->getLayout();
            $layout->getUpdate()->addHandle('quickview_product_view');
        }
        return parent::execute();
    }
}

This means when we call product’s URL with iframe as GET parameter, we will be able to modify its layout since we have brand new handle in that case.
So, let’s do it:
app/code/Inchoo/QuickView/view/frontend/layout/quickview_product_view.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="empty"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
 
    <update handle="empty"/>
 
    <html>
        <attribute name="class" value="quickview-scroll"/>
    </html>
 
    <body>
        <attribute name="class" value="quickview-override"/>
 
        <referenceContainer name="product.page.products.wrapper" remove="true" />
        <referenceContainer name="product.info.details" remove="true" />
        <referenceBlock name="reviews.tab" remove="true" />
        <referenceBlock name="product.info.details" remove="true" />
        <referenceBlock name="product.info.description" remove="true" />
        <referenceBlock name="product.info.overview" remove="true" />
        <referenceBlock name="authentication-popup" remove="true" />
    </body>
</page>

This is where you come in place. Edit that page layout as you wish. I removed few elements for example.

Hm… I have some feeling that I forgot something…
Ah yes 🙂

JavaScript

This is where we need to do most of the magic.
app/code/Inchoo/QuickView/view/frontend/web/js/product/productlist/item/quickview.js

define([
    'jquery',
    'Magento_Ui/js/modal/modal',
    'mage/loader',
    'Magento_Customer/js/customer-data'
], function ($, modal, loader, customerData) {
    'use strict';
 
    return function(config, node) {
 
        var product_id = jQuery(node).data('id');
        var product_url = jQuery(node).data('url');
 
        var options = {
            type: 'popup',
            responsive: true,
            innerScroll: false,
            title: $.mage.__('Quick View'),
            buttons: [{
                text: $.mage.__('Close'),
                class: 'close-modal',
                click: function () {
                    this.closeModal();
                }
            }]
        };
 
        var popup = modal(options, $('#quickViewContainer' + product_id));
 
        $("#quickViewButton" + product_id).on("click", function () {
            openQuickViewModal();
        });
 
        var openQuickViewModal = function () {
            var modalContainer = $("#quickViewContainer" + product_id);
            modalContainer.html(createIframe());
 
            var iframe_selector = "#iFrame" + product_id;
 
            $(iframe_selector).on("load", function () {
                modalContainer.addClass("product-quickview");
                modalContainer.modal('openModal');
                this.style.height = this.contentWindow.document.body.scrollHeight+10 + 'px';
                this.style.border = '0';
                this.style.width = '100%';
                observeAddToCart(this);
            });
        };
 
        var observeAddToCart = function (iframe) {
 
            var doc = iframe.contentWindow.document;
 
            $(doc).contents().find('#product_addtocart_form').submit(function(e) {
                e.preventDefault();
                $.ajax({
                    data: $(this).serialize(),
                    type: $(this).attr('method'),
                    url: $(this).attr('action'),
                    success: function(response) {
                        customerData.reload("cart");
                        customerData.reload("messages");
                        $(".close-modal").trigger("click");
                        $('[data-block="minicart"]').find('[data-role="dropdownDialog"]').dropdownDialog("open");
                    }
                });
            });
        };
 
        var createIframe = function () {
            return $('<iframe />', {
                id: 'iFrame' + product_id,
                src: product_url + "?iframe=1"
            });
        }
    };
});

This is where you will find most of BUGs (if any) 😀
Idea is to use Magento’s default modal window, open it with button we added few steps earlier, create iframe, load product page in an iframe and most importantly observe submit event on add to cart form so we can close the window once the product is added.

That should be it in its simplest form…

Note that this was created mostly for the purpose of this article and there is probably few things that should be optimized, but it could give you the idea of how to make something like that.
Test it before you do anything serious with it and good luck!

Happy coding!

You made it all the way down here so you must have enjoyed this post! You may also like:

Mar 21, 2017

How I learned to stop worrying and love 3rd party modules for Magento

/ Leave a comment
May 31, 2016

Optimize Elasticsearch autocomplete URL for Google Analytics

/ Leave a comment
Dec 11, 2015

Inchoo’s compatibility extension for Magento 1 and PHP 7

/ Leave a comment

1 comment

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.