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/simplemagento/QuickView/registration.php and add this code:
<?php
/**
* @category simplemagento
* @package simplemagento_QuickView
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'simplemagento_QuickView',
__DIR__
);
We need this to register our new module.
Let’s also create app/code/simplemagento/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="simplemagento_QuickView" setup_version="1.0.0">
<sequence>
<module name="Magento_Catalog"/>
<module name="Magento_Customer"/>
</sequence>
</module>
</config>
and app/code/simplemagento/QuickView/composer.json
{
"name": "simplemagento/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": {
"simplemagento\\QuickView\\": ""
}
}
}
At this point you should be able to enable this module simply by running:
php bin/magento module:enable simplemagento_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/simplemagento/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="simplemagento_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/simplemagento/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="simplemagento\QuickView\Controller\Product\View" />
</config>
That’s it, now we need app/code/simplemagento/QuickView/Controller/Product/View.php
<?php
namespace simplemagento\QuickView\Controller\Product;
use Magento\Catalog\Controller\Product\View as CatalogView;
/**
* Class View
*
* @package simplemagento\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/simplemagento/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/simplemagento/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!