Override Checkout Street Address Placeholder in Magento 2

In this article, I am going to explain how we can override checkout street address placeholder of customer address at checkout.

Wishusucess_StreetAddressPlaceholder is a Magento 2 plugin which has developed by a Wishusucess Magento 2 expert developer to override the Magento 2 customer street address at the checkout.

By installing this plugin you simply can get change the placeholder of the checkout street address.

 

Override Checkout Street Address Placeholder

When we override Magento 2 customer checkout address placeholder then we need to create only four files to create get hose facilities.

app/code/Wishusucess/StreetAddressPlaceholder/registration.php

app/code/Wishusucess/StreetAddressPlaceholder/etc/module.xml

app/code/Wishusucess/StreetAddressPlaceholder/etc/di.xml

app/code/Wishusucess/StreetAddressPlaceholder/Plugin/Checkout/Block/Checkout/AttributeMerger/Plugin.php

 

Register Your Module StreetAddressPlaceholder

We have to register our Magento 2 plugin first through the registration.php file so we need to create this file.

app/code/Wishusucess/StreetAddressPlaceholder/registration.php

<?php
/*
* @Author Hemant Singh
* @Developer Hemant Singh
* @Module Wishusucess_StreetAddressPlaceholder
* @copyright Copyright (c) Wishusucess (http://www.wishusucess.com/)
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Wishusucess_StreetAddressPlaceholder',
__DIR__
);

 

Give Override Plugin Basic Information

This file basically consists of the basic information about your plugin and module so here we have to give the plugin name and schema version so when we run Magento setup: upgrade command then this information will store in the setup_version DB table.

app/code/Wishusucess/StreetAddressPlaceholder/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="Wishusucess_StreetAddressPlaceholder" setup_version="2.0.0" />
</config>

 

Create Dependency Injection File For Plugin

When we develop a plugin to like StreetAddressPlaceholder then the di.xml file consists of the design pattern which means Dependency Injection will allow the object

Magento\Checkout\Block\Checkout\AttributeMerger

to declare its dependencies to an external object

Wishusucess\StreetAddressPlaceholder\Plugin\Checkout\Block\Checkout\AttributeMerger\Plugin

that supplies those dependencies.

So here plugin class

(Wishusucess\StreetAddressPlaceholder\Plugin\Checkout\Block\Checkout\AttributeMerger\Plugin) concrete implementations for

Magento\Checkout\Block\Checkout\AttributeMerger interfaces.

app/code/Wishusucess/StreetAddressPlaceholder/etc/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\Block\Checkout\AttributeMerger">
<plugin name="shippingAddress" type="Wishusucess\StreetAddressPlaceholder\Plugin\Checkout\Block\Checkout\AttributeMerger\Plugin"/>

</type>
</config>

 

Create Plugin Class For Override Checkout Street Address

This class will allow you to change the behavior of the core Magento class. Here you can give your desire placeholder for the customer street address input field.

app/code/Wishusucess/StreetAddressPlaceholder/Plugin/Checkout/Block/Checkout/AttributeMerger/Plugin.php

<?php
/*
* @Author Hemant Singh
* @Developer Hemant Singh
* @Module Wishusucess_StreetAddressPlaceholder
* @copyright Copyright (c) Wishusucess (http://www.wishusucess.com/)
*/
namespace Wishusucess\StreetAddressPlaceholder\Plugin\Checkout\Block\Checkout\AttributeMerger;

class Plugin
{
public function afterMerge(\Magento\Checkout\Block\Checkout\AttributeMerger $subject, $result)
{

if (array_key_exists('street', $result)) {
$result['street']['children'][0]['placeholder'] = __('Address Line 1');
$result['street']['children'][1]['placeholder'] = __('(Optional: Apt, Building, etc.)');
$result['street']['children'][2]['placeholder'] = __('Landmark');
}

if (array_key_exists('prefix', $result)) {
$result['prefix']['placeholder'] = __('Title');
}

if (array_key_exists('firstname', $result)) {
$result['firstname']['placeholder'] = __('First Name');
}

if (array_key_exists('lastname', $result)) {
$result['lastname']['placeholder'] = __('Last Name');
}

if (array_key_exists('telephone', $result)) {
$result['telephone']['placeholder'] = __('Phone Number');
}

if (array_key_exists('region_id', $result)) {
$result['region_id']['placeholder'] = __('State/Province');
}

if (array_key_exists('city', $result)) {
$result['city']['placeholder'] = __('City');
}

if (array_key_exists('postcode', $result)) {
$result['postcode']['placeholder'] = __('Zip/Postal Code');
}

return $result;

}

}

 

Now, Run Following Command:

php bin/magento setup:upgrade

php bin/magento setup:di:compile

php bin/magento setup:static-content:deplpy -f

php bin/magento cache:clean

 

Override Checkout Street Address Placeholder-min

Download Link:

Wishusucess Checkout Street Address Placeholder Plugin in Magento 2

 

Hire Magento 2 Expert Developer to Develop Your Store

 

Related Post:

Custom Shipping Text Filed: Show Custom Text Magento 2

Search AutoComplete: Magento 2 Module Add All Category for Search

Sort By Price: Add Sort By Price High to Low & Low To High in Magento 2

 

Recommended Post:

Magento 2.4 Installation Guide: How to Install Magento 2.4.2

Magento Store: Best 36 Magento Websites Example in The World

SEO Packages: How Much Do SEO Packages Cost in India, SEO Pricing

 

Custom Shipping Text Filed: Show Custom Text Magento 2

Here, In this article, I am going to explain how we can add a custom shipping text field in Magento 2 admin shipping method section.

Wishusucess ShippingTexarea Magento 2 extension will add a custom text field in Flat Rate shipping method, Table Rate shipping method, and Free Shipping method.

 

Custom Shipping TextArea Module Basic File

In order to get these features in Magento 2 admin shipping method, we need only 3 files to create then we can easily achieve this functionality. files are given in below.

app/code/Wishusucess/ShippingTexarea/registration.php

app/code/Wishusucess/ShippingTexarea/etc/module.xml

app/code/Wishusucess/ShippingTexarea/adminhtml/system.xml

 

 

Register Custom Shipping Text Module

As we know this is one of the most basic files for any kind of Magento 2 module. So we have created a registration.php file to get registered with our custom shipping text method module.

app/code/Wishusucess/ShippingTexarea/registration.php

<?php
/*
* @Author Hemant Singh
* @Developer Hemant Singh
* @Module Wishusucess_ShippingTextarea
* @copyright Copyright (c) Wishusucess (http://www.wishusucess.com/)
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Wishusucess_ShippingTexarea',
__DIR__
);

 

Give Custom Shipping Module Name

Here you have to give the module basic information through the XML file. It's a configuration file for the custom shipping text module.

app/code/Wishusucess/ShippingTexarea/etc/module.xml directory module. This file is a basic file that always needs to create a module across all Magento 2 configuration files.

app/code/Wishusucess/ShippingTexarea/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="Wishusucess_ShippingTexarea" setup_version="1.0.1">
</module>
</config>

 

Create Custom Shipping Text Field Through XML File

Now we have to create a system.xml file This configuration file is used to create configuration fields in Magento 2 System Configuration.

This file gives options to add a custom field on Magento 2 admin side. Here we can define different types of entities.

The most important thing which we need to remember about this file is the relationship between tabs, sections, groups, and fields.

app/code/Wishusucess/ShippingTexarea/adminhtml/system.xml

<?xml version="1.0"?>
<!--
/*
* @Author Hemant Singh
* @Developer Hemant Singh
* @Module Wishusucess_ShippingTextarea
* @copyright Copyright (c) Wishusucess (http://www.wishusucess.com/)
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<section id="carriers" type="text" sortOrder="320" showInDefault="1" showInWebsite="1" showInStore="1">
<group id="flatrate" translate="label" type="textarea" sortOrder="0" showInDefault="1" showInWebsite="1" showInStore="1">
<field id="customtext" translate="label" type="textarea" sortOrder="9" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Displayed Custom Message</label>
</field>
</group>
<group id="tablerate" translate="label" type="textarea" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<field id="customtext" translate="label" type="textarea" sortOrder="101" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Displayed Custom Message</label>
</field>
</group>
<group id="freeshipping" translate="label" type="textarea" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1">
<field id="customtext" translate="label" type="textarea" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Displayed Custom Message</label>
</field>
</group>
</section>
</system>
</config>

 

Now, Run Following Command:

php bin/magento setup:upgrade

php bin/magento setup:di:compile

php bin/magento setup:static-content:deplpy -f

php bin/magento cache:clean

 

Now check the result in Magento 2

Admin > Stores > Configuration > Sales > Shipping Method

Custom Shipping Text Field

 

Added Custom Shipping Text Area in Free Shipping Section

Magento 2 Custom Shipping Field

 

Download Link:

Wishusucess Custom Shipping Text Area Extension in Magento 2

 

Hire Magento 2 Expert Developer to Develop Your Store

 

Related Post:

Price Slider: Create Ajax Price Slider Filter in Magento 2

Search AutoComplete: Magento 2 Module Add All Category for Search

Sort By Price: Add Sort By Price High to Low & Low To High in Magento 2

 

Recommended Post:

Magento 2.4 Installation Guide: How to Install Magento 2.4.2

Magento Store: Best 36 Magento Websites Example in The World

SEO Packages: How Much Do SEO Packages Cost in India, SEO Pricing

Price Slider: Create Ajax Price Slider Filter in Magento 2

Customer experiences most important factor in any kind of business success. When it comes to Magento 2 Store category page then Price Slider in Layered Navigation also use to provide a great experience to the customer.

Wishusucess PriceSlider/ Range filter Magento 2 free extentions offers that kind of option to add these features in your store without doing any changes in the code.

This feature is complete with full features for the customer which provides an easy slide filter for the product in the Layered Navigation filter on the category list page.

Magento 2 Price Filter

 

Wishusucess Price Filter Works

When you enable these features then your customer easily can slide price from any minimum point to any number of maximum points and they can filter the product.

It's a fully Ajax Slider filter which don't load your whole page while filter slide-in navigation filter.

 

Ajax Price Slider Filter Basic File in Magento 2

In order to get these features on the category page, we have to create a minimum of seven files. and all these basic files are given below.

app/code/Wishusucess/Priceslider/registration.php

app/code/Wishusucess/Priceslider/etc/module.xml

app/code/Wishusucess/Priceslider/etc/di.xml

app/code/Wishusucess/Priceslider/Block/FilterRenderer.php

app/code/Wishusucess/Priceslider/view/frontend/layout/catalog_category_view_type_layered.xml

app/code/Wishusucess/Priceslider/view/frontend/templates/filter.phtml

app/code/Wishusucess/Priceslider/view/frontend/templates/view.phtml

 

Importance of Price Slider Filter on List Page

This option gives the best way for customers to respond to price.

If we will check to analyze the data then you will get like 85% of customers do online price research so it's showing that price is the most popular sorting option which can increase your sales or decrease your sales if these options will be not good.

Most retail customers always have their budget in the mind for a price range for an item. So if your store will have more options to choose from then it means you will have more sales.

 

Step 1: Registration of Your Module

app/code/Wishusucess/Priceslider/registration.php

<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
/*
|--------------------------------------------------------------------------
| Wishsucess PriceSlider Filter
|--------------------------------------------------------------------------
|
| PriceSlider Filter
|
| @author Hemant Singh
| http://www.wishusucess.com/
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Wishusucess_Priceslider',
__DIR__
);

 

Step 2: Give Basic Information of Module

app/code/Wishusucess/Priceslider/etc/module.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
<module name="Wishusucess_Priceslider" setup_version="0.0.2"></module>
</config>

 

Step 3:

app/code/Wishusucess/Priceslider/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<preference for="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" type="Wishusucess\Priceslider\Block\FilterRenderer" />
<type name="Wishusucess\Priceslider\Block\FilterRenderer">
<plugin name="swatches_layered_renderer" type="Magento\Swatches\Model\Plugin\FilterRenderer" sortOrder="1" />
</type>
</config>

 

Magento 2 Get Price Range for Price Slider Filter

Here in this step, we have to create a block that will get the price range in layered navigation and return to filter price.

app/code/Wishusucess/Priceslider/Block/FilterRenderer.php

<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
/*
|--------------------------------------------------------------------------
| Wishsucess PriceSlider Filter
|--------------------------------------------------------------------------
|
| PriceSlider Filter
|
| @author Hemant Singh
| http://www.wishusucess.com/
*/
namespace Wishusucess\Priceslider\Block;

use Magento\Catalog\Model\Layer\Filter\FilterInterface;

class FilterRenderer extends \Magento\LayeredNavigation\Block\Navigation\FilterRenderer
{
/**
* @param FilterInterface $filter
* @return string
*/
public function render(FilterInterface $filter)
{
$this->assign('filterItems', $filter->getItems());
$this->assign('filter' , $filter);
$html = $this->_toHtml();
$this->assign('filterItems', []);
return $html;
}

public function getPriceRange($filter){
$Filterprice = array('min' => 0 , 'max'=>0);
if($filter instanceof \Magento\CatalogSearch\Model\Layer\Filter\Price){
$priceArr = $filter->getResource()->loadPrices(10000000000);
$Filterprice['min'] = reset($priceArr);
$Filterprice['max'] = end($priceArr);
}
return $Filterprice;
}

public function getFilterUrl($filter){
$query = ['price'=> ''];
return $this->getUrl('*/*/*', ['_current' => true, '_use_rewrite' => true, '_query' => $query]);
}
}

 

Set Price Slider Template in Catalog Navigation Filter

app/code/Wishusucess/Priceslider/view/frontend/layout/catalog_category_view_type_layered.xml

<?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>
<referenceBlock name="catalog.navigation.renderer">
<action method="setTemplate">
<argument name="template" xsi:type="string">Wishusucess_Priceslider::filter.phtml</argument>
</action>
</referenceBlock>
</body>
</page>

 

Step 6:

app/code/Wishusucess/Priceslider/view/frontend/templates/filter.phtml

<?php /** * Template for filter items block * * @var $block \Magento\LayeredNavigation\Block\Navigation\FilterRenderer */ /* |-------------------------------------------------------------------------- | Wishsucess PriceSlider Filter |-------------------------------------------------------------------------- | | PriceSlider Filter | | @author Hemant Singh | http://www.wishusucess.com/ */ ?>

<?php
/**
* Template for filter items block
*
* @var $block \Magento\LayeredNavigation\Block\Navigation\FilterRenderer
*/
?>
<?php

?>
<?php if($filter instanceof Magento\CatalogSearch\Model\Layer\Filter\Price ):?>
<?php $range = $this->getPriceRange($filter);?>
<?php $url = $this->getFilterUrl($filter);?>
<script>
var price_url = "<?=$url;?>";
require([
'jquery',
'priceUtils',
"jquery/ui",
'domReady!'
], function($,utils){
updateLabel = function() {
var priceFormat = <?php /* @escapeNotVerified */ echo $this->helper('Magento\Tax\Helper\Data')->getPriceFormat($block->getStore()); ?>;
var min = utils.formatPrice($( "#price-slider" ).slider( "values", 0 ), priceFormat);
var max = utils.formatPrice($( "#price-slider" ).slider( "values", 1 ), priceFormat);
$( "#amount" ).val(min + " - " + max);
};
$("div#price-slider").slider({
range: true,
min: <?=$range['min']?>,
max: <?=$range['max']?>,
values: [ <?=$range['min']?>, <?=$range['max']?> ],
slide: function( event, ui ) {
updateLabel();
},
change: function( event, ui ) {
window.location.href = price_url.replace("price=","price="+ui.values[0]+"-"+ui.values[1]);
}
});
updateLabel();
});
</script>

<p>
<label for="amount"><?= __('Price range:') ?></label>
<input type="text" id="amount" readonly style="border:0; color:#f6931f; font-weight:bold;">
</p>
<div id="price-slider"></div>

<?php else:?>
<ol class="items">
<?php foreach ($filterItems as $filterItem): ?>
<li class="my item">
<?php if ($filterItem->getCount() > 0): ?>
<a href="<?php echo $block->escapeUrl($filterItem->getUrl()) ?>">
<?php /* @escapeNotVerified */ echo $filterItem->getLabel() ?>
<?php if ($this->helper('\Magento\Catalog\Helper\Data')->shouldDisplayProductCountOnLayer()): ?>
<span class="count"><?php /* @escapeNotVerified */ echo $filterItem->getCount()?><span class="filter-count-label">
<?php if ($filterItem->getCount() == 1):?> <?php /* @escapeNotVerified */ echo __('item')?><?php else:?> <?php /* @escapeNotVerified */ echo __('items') ?><?php endif;?></span></span>
<?php endif; ?>
</a>
<?php else:?>
<?php /* @escapeNotVerified */ echo $filterItem->getLabel() ?>
<?php if ($this->helper('\Magento\Catalog\Helper\Data')->shouldDisplayProductCountOnLayer()): ?>
<span class="count"><?php /* @escapeNotVerified */ echo $filterItem->getCount()?><span class="filter-count-label">
<?php if ($filterItem->getCount() == 1):?><?php /* @escapeNotVerified */ echo __('item')?><?php else:?><?php /* @escapeNotVerified */ echo __('items') ?><?php endif;?></span></span>
<?php endif; ?>
<?php endif; ?>
</li>
<?php endforeach ?>
</ol>
<?php endif;?>

 

Step 7:

app/code/Wishusucess/Priceslider/view/frontend/templates/view.phtml

<?php
/**
* Category layered navigation
*
* @var $block \Magento\LayeredNavigation\Block\Navigation
*/
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
/*
|--------------------------------------------------------------------------
| Wishsucess PriceSlider Filter
|--------------------------------------------------------------------------
|
| PriceSlider Filter
|
| @author Hemant Singh
| http://www.wishusucess.com/
*/
?>

<?php
/**
* Category layered navigation
*
* @var $block \Magento\LayeredNavigation\Block\Navigation
*/
?>

<?php if ($block->canShowBlock()): ?>
<div class="block filter" id="layered-filter-block" data-mage-init='{"collapsible":{"openedState": "active", "collapsible": true, "active": false, "collateral": { "openedState": "filter-active", "element": "body" } }}'>
<?php $filtered = count($block->getLayer()->getState()->getFilters()) ?>
<div class="block-title filter-title" data-count="<?php /* @escapeNotVerified */ echo $filtered; ?>">
<strong data-role="title"><?php /* @escapeNotVerified */ echo __('Shop By') ?></strong>
</div>
<div class="block-content filter-content">
<?php echo $block->getChildHtml('state') ?>

<?php if ($block->getLayer()->getState()->getFilters()): ?>
<div class="block-actions filter-actions">
<a href="<?php /* @escapeNotVerified */ echo $block->getClearUrl() ?>" class="action clear filter-clear"><span><?php /* @escapeNotVerified */ echo __('Clear All') ?></span></a>
</div>
<?php endif; ?>
<?php $wrapOptions = false; ?>
<?php foreach ($block->getFilters() as $filter): ?>
<?php if ($filter->getItemsCount()): ?>
<?php if (!$wrapOptions): ?>
<strong role="heading" aria-level="2" class="block-subtitle filter-subtitle"><?php /* @escapeNotVerified */ echo __('Shopping Options') ?></strong>
<div class="filter-options" id="narrow-by-list" data-role="content" data-mage-init='{"accordion":{"openedState": "active", "collapsible": true, "active": false, "multipleCollapsible": false}}'>
<?php $wrapOptions = true; endif; ?>
<div data-role="collapsible" class="filter-options-item">
<div data-role="title" class="filter-options-title"><?php /* @escapeNotVerified */ echo __($filter->getName()) ?></div>
<div data-role="content" class="filter-options-content"><?php /* @escapeNotVerified */ echo $block->getChildBlock('renderer')->render($filter); ?></div>
</div>
<?php endif; ?>
<?php endforeach; ?>
<?php if ($wrapOptions): ?>
</div>
<?php else: ?>
<script>
require([
'jquery'
], function ($) {
$('#layered-filter-block').addClass('filter-no-options');
});
</script>
<?php endif; ?>
</div>
</div>
<?php endif; ?>

 

Now, Run Following Command:

php bin/magento setup:upgrade

php bin/magento setup:di:compile

php bin/magento setup:static-content:deplpy -f

php bin/magento cache:clean

 

Magento 2 Price Slider on List Page

 

Download Link:

Wishusucess PriceSlider Extension in Magento 2

 

Hire Magento 2 Expert Developer to Develop Your Store

 

Related Post:

Wishusucess AdminMenu: How to Create Magento 2 Admin Menu Module

Search AutoComplete: Magento 2 Module Add All Category for Search

Sort By Price: Add Sort By Price High to Low & Low To High in Magento 2

 

Recommended Post:

Magento 2.4 Installation Guide: How to Install Magento 2.4.2

Magento Store: Best 36 Magento Websites Example in The World

SEO Packages: How Much Do SEO Packages Cost in India, SEO Pricing

 

Create Customer Mutation: Magento 2 GraphQL Mutation

When we develop a shopping app in Magento using some other library like RackJS then we need to create mutation to load the data and retrieve it in the library like ReackJS.  Here we have given an example for Create Customer mutation in Magento 2 for a new customer account.

So in order to get the modified information about a customer, it's always good to use customer tokens in GraphQL calls in the header.

 

Create Customer Mutation for Magento 2 SignUp

Here we have created a sample example for mutation creation in GraphQL. This shows how we can receive the data of Magento 2customer account SignUp using GraphQL.

mutation {
createCustomer(
input: {
firstname: "Hemant"
lastname: "Singh"
email: "cs.hemantsingh@gmail.com"
password: "Admin$#21"
is_subscribed: true
}
) {
customer {
firstname
lastname
email
is_subscribed
}
}
}

 

Response of Create Customer Mutation Magento 2

Here is how to get the response when we type the query in Altair GraphQL tools.

Data we get in the JSON format.
Create Customer Mutation GraphQL

 

Magento 2 Customer Retrieve Data in GraphQL

When we type the query and the customer doesn't exist then it shows an error like the below image. Basically, it's not an error it's a message response that the customer doesn't exist.

{
customer {
firstname
lastname
suffix
email
addresses {
firstname
lastname
street
city
region {
region_code
region
}
postcode
country_code
telephone
}
}
}

 

Response When Customer Not Exist

Customer Not Exist

 

Generate Customer Tokens In GraphQL

If the customer already created an account then we can get the generated customer tokens using the below GraphQL query.

So this token basically we use to authorize the request header field for any queries and mutations.

mutation {
generateCustomerToken(email: "cs.hemantsingh@gmail.com", password: "Admin$#21") {
token
}
}

Response

Generate Customer Tokens

So when we try to generate the customer tokens in Magento 2 Using GraphQL then mutation needs a customer email address and password in the payload, as you can see in the above example how we have given customer details like email and password.

Token Validity in Magento is generally for 1 hour.

Change Token Validity: Admin > Stores > Settings > Configuration > Services > OAuth > Access Token Expiration > Customer Token Lifetime.

 

 

Recommended Post:

WhatsApp Chat: Add Magento 2 Whatsapp Extension

Sort By Price: Add Sort By Price High to Low & Low To High in Magento 2

Magento 2 SmartSearch: Best Smart Search Auto Complete Module

 

WhatsApp Chat: Add Magento 2 Whatsapp Extension

In this article, we are going to tell you how you can create a free Magento 2 WhatsApp Chat Set extension for instant communication with customers and allow them to share your product with their contact details.

Magento 2 WhatsApp Chat Button

 

Magento 2 WhatsApp Chat Features

  • Easy to use
  • You can customize your message from the Magento admin.
  • Allow you to set button sizes like small, medium, large from the admin setting.
  • Gives you the option to change the default WhatsApp mobile number from the Magento admin.
  • Easy customization option from admin as per your requirements.
  • Easy to Install and configure

WhatsApp Chat Admin Configuration

 

Magento 2 WhatsApp Chat Module Basic File

Wishuscess Magento expert developer developed a free whats app chat extension which allows changing the setting from admin side like its's provide the options to change the number from admin and set the default message.

So for that, you need to create some basic files and that basic files are:

app/code/Wishusucess/WhatsAppChat/registration.php

app/code/Wishusucess/WhatsAppChat/etc/module.xml

app/code/Wishusucess/WhatsAppChat/etc/config.xml

app/code/Wishusucess/WhatsAppChat/adminhtml/system.xml

app/code/Wishusucess/WhatsAppChat/Helper/Data.php

app/code/Wishusucess/WhatsAppChat/view/frontend/layout/default.xml

app/code/Wishusucess/WhatsAppChat/view/frontend/templates/button.phtml

app/code/Wishusucess/WhatsAppChat/view/frontend/web/css/whatsapp-chat.css

app/code/Wishusucess/WhatsAppChat/view/frontend/web/images/button.png

 

Register Your WhatsApp Chat Module

app/code/Wishusucess/WhatsAppChat/registration.php

<?php
/*
|--------------------------------------------------------------------------
| Wishsucess WhatsAppChat Module
|--------------------------------------------------------------------------
|
| WhatsAppChat Extension To Share Product in Magento 2
|
| @author Hemant Singh
| http://www.wishusucess.com/
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Wishusucess_WhatsAppChat',
__DIR__
);

 

Give The Basic Information of Module

app/code/Wishusucess/WhatsAppChat/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
<module name="Wishusucess_WhatsAppChat" setup_version="1.0.0"></module>
</config>

 

Set Default WhatsApp Chat Number in Magento 2

This file allows you to set the default setting for your What's App Chat Extensions. Here you can set the default Whats App number and default message.

app/code/Wishusucess/WhatsAppChat/etc/config.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<contact>
<whatsapp_chat>
<status>1</status>
<phone_number>+91-79922XXXXX</phone_number>
<message>Hello! I am interested in your product</message>
</whatsapp_chat>
</contact>
</default>
</config>

 

Manage Configuration From Magento 2 Admin

In Wishusucess What's App Chat Extension this system.xml file allows you to manage your module configuration from the Magento backend.

app/code/Wishusucess/WhatsAppChat/adminhtml/system.xml

<?xml version="1.0"?>
<!--
/**
* Wishsucess WhatsAppChat Module
* WhatsAppChat Extension To Share Product in Magento 2
* See COPYING.txt for license details.
* http://www.wishusucess.com/
* @author Hemant Singh
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<section id="contact" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
<class>separator-top</class>
<label>Contacts</label>
<tab>general</tab>
<resource>Wishusucess_WhatsAppChat::contact</resource>
<group id="whatsapp_chat" translate="label" type="text" sortOrder="51" showInDefault="1" showInWebsite="1" showInStore="1">
<label>WhatsApp Chat</label>
<field id="status" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
<label>Status</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Enable/ disable Whats App Chat</comment>
</field>
<field id="phone_number" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
<label>Phone Number</label>
<comment>Full phone number in international format. Example: +91xxxxx</comment>
<depends>
<field id="status">1</field>
</depends>
</field>
<field id="message" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
<label>Message</label>
<comment>Pre-filled message that will automatically appear in the text field of a chat</comment>
<depends>
<field id="status">1</field>
</depends>
</field>
</group>
</section>
</system>
</config>

 

Get WhatsApp Chat Data in Magento 2

Through the Data.php file, you can get your mobile number and text message in your what's app chat extension.

This class provides you the functionalities to use your class anywhere on the website, You can call this in view/frontend templates as well as block, controller files.

app/code/Wishusucess/WhatsAppChat/Helper/Data.php

<?php
/*
|--------------------------------------------------------------------------
| Wishsucess WhatsAppChat Module
|--------------------------------------------------------------------------
|
| WhatsAppChat Extension To Share Product in Magento 2
|
| @author Hemant Singh
| http://www.wishusucess.com/
*/
namespace Wishusucess\WhatsAppChat\Helper;

class Data extends \Magento\Framework\App\Helper\AbstractHelper
{

public function __construct(
\Magento\Framework\App\Helper\Context $context
) {
parent::__construct($context);
}

/**
* Return status
*
* @return string
*/

public function getStatus(){
return $this->scopeConfig->getValue('contact/whatsapp_chat/status', 
\Magento\Store\Model\ScopeInterface::SCOPE_STORE);
}

/**
* Return phone
*
* @return string
*/

public function getPhone(){
return $this->scopeConfig->getValue('contact/whatsapp_chat/phone_number', 
\Magento\Store\Model\ScopeInterface::SCOPE_STORE);
}

/**
* Return message
*
* @return string
*/

public function getMessage(){
return $this->scopeConfig->getValue('contact/whatsapp_chat/message', 
\Magento\Store\Model\ScopeInterface::SCOPE_STORE);
}
}

 

Set Default Chat Button for Everywhere

app/code/Wishusucess/WhatsAppChat/view/frontend/layout/default.xml

<?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">
<head>
<css src="Wishusucess_WhatsAppChat::css/whatsapp-chat.css" />
</head>
<body>
<referenceContainer name="before.body.end">
<block class="Magento\Framework\View\Element\Template" name="dangs_whatsapp_chat" 
template="Wishusucess_WhatsAppChat::button.phtml" 
before="before.body.end" cacheable="false">
</block>
</referenceContainer>
</body>
</page>

 

Create Chat Template File

app/code/Wishusucess/WhatsAppChat/view/frontend/templates/button.phtml

<?php $helper = $this->helper('Wishusucess\WhatsAppChat\Helper\Data');?>

<?php if($helper->getStatus()): ?>
<div id="wachat">
<a href="https://web.whatsapp.com/send?phone=<?php echo $helper->getPhone(); ?>&amp;text=<?php echo $helper->getMessage(); ?>" onclick="gtag('event', 'WhatsApp', {'event_action': 'whatsapp_chat', 'event_category': 'Chat', 'event_label': 'Chat_WhatsApp'});" target="_blank" class="btn-web">
<img src="<?php echo $this->getViewFileUrl('Wishusucess_WhatsAppChat::images/button.png'); ?>" alt="WA button">
</a>

<a href="https://wa.me/085236725506?text=<?php echo $helper->getMessage(); ?>" onclick="gtag('event', 'WhatsApp', {'event_action': 'whatsapp_chat', 'event_category': 'Chat', 'event_label': 'Chat_WhatsApp'});" target="_blank" class="btn-mobile">
<img src="<?php echo $this->getViewFileUrl('Wishusucess_WhatsAppChat::images/button.png'); ?>" alt="WA button">
</a>
</div>

<style type="text/css">
@media(max-width: 768px) {
#wachat .btn-web{
display: none;
}
}
@media(min-width: 768px) {
#wachat .btn-mobile{
display: none;
}
}
</style>
<?php endif; ?>

 

Apply CSS on Your What's App Chat Button

app/code/Wishusucess/WhatsAppChat/view/frontend/web/css/whatsapp-chat.css

#wachat a {
position: fixed;
z-index: 9999;
right: 0;
float: right;
top: 40%;
margin-top: -25px;
cursor: pointer;
min-width: 50px;
max-width: 150px;
color: #fff;
text-align: center;
padding: 10px;
margin: 0 auto 0 auto;
background: #20b038;
-webkit-transition: All .5s ease;
-moz-transition: All .5s ease;
-o-transition: All .5s ease;
-ms-transition: All .5s ease;
transition: All .5s ease;
}

#wachat a img{
width: 50px;
}

Add Your Favorite What's App Chat Button

app/code/Wishusucess/WhatsAppChat/view/frontend/web/images/button.png

 

Now, Run Following Command:

php bin/magento setup:upgrade

php bin/magento setup:di:compile

php bin/magento setup:static-content:deplpy -f

php bin/magento cache:clean

 

Magento 2 WhatsApp Chat Convert Prospects into Customers

We have developed this product in such a way that this Wishsuccess Magento 2 What's App chat module will boost your store sales and attract a wider audience for your store.

And we have also given the functionality which will give you the flexibility to change the message while sharing the product and customers can share a product with URLs along with your customized messages and the product title, description, etc.

You can Hire Magento 2 Developer to add more functionality as per your needs.

 

Download Link:

Wishusucess What's App Chat Extension in Magento 2

 

Related Post:

Wishusucess AdminMenu: How to Create Magento 2 Admin Menu Module

Search AutoComplete: Magento 2 Module Add All Category for Search

Sort By Price: Add Sort By Price High to Low & Low To High in Magento 2

 

Recommended Post:

Magento 2.4 Installation Guide: How to Install Magento 2.4.2

Magento Store: Best 36 Magento Websites Example in The World

SEO Packages: How Much Do SEO Packages Cost in India, SEO Pricing

 

 

Sort By Price: Add Sort By Price High to Low & Low To High in Magento 2

When a customer comes to the store then sometimes they try to Sort By Price product in cheapest order or low to high order product or high to low order product.

So here we have developed a module that provides the facilities to sort the product based on the price in ascending order and descending order.

Sort By Price Filter in Magento 2

Magento 2 Sort By Price Filter Basic File

In order to create a SortByPrice module in ascending and descending order, we have to create four basic files.

app/code/Wishusucess/SortByPrice/registration.php

app/code/Wishusucess/SortByPrice/etc/module.xml

app/code/Wishusucess/SortByPrice/Plugin/Catalog/Block/Toolbar.php

app/code/Wishusucess/SortByPrice/Plugin/Catalog/Model/Config.php

 

Step 1:

Firstly we have to register our module through the registration.php file.

app/code/Wishusucess/SortByPrice/registration.php

<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
/*
|--------------------------------------------------------------------------
| Wishsucess SortByPrice Filter
|--------------------------------------------------------------------------
|
| SortByPrice High To Low and Low To High Filter
|
| @author Hemant Singh
| http://www.wishusucess.com/
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Wishusucess_SortByPrice',
__DIR__
);

 

Step 2:

app/code/Wishusucess/SortByPrice/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
<module name="Wishusucess_SortByPrice" setup_version="1.0.0" />
</config>

 

Step 3: Sort By Price Low To High Filter Toolbar

app/code/Wishusucess/SortByPrice/Plugin/Catalog/Block/Toolbar.php

<?php
/*
|--------------------------------------------------------------------------
| Wishsucess SortByPrice Filter
|--------------------------------------------------------------------------
|
| SortByPrice High To Low and Low To High Filter
|
| @author Hemant Singh
| http://www.wishusucess.com/
*/
namespace Wishusucess\SortByPrice\Plugin\Catalog\Block;
class Toolbar
{
public function aroundSetCollection(\Magento\Catalog\Block\Product\ProductList\Toolbar $subject,
\Closure $proceed, $collection)
{
$currentOrder = $subject->getCurrentOrder();
$result = $proceed($collection);
if($currentOrder)
{
if($currentOrder == 'high_to_low')
{
$subject->getCollection()->setOrder('price', 'desc');
}
elseif ($currentOrder == 'low_to_high')
{
$subject->getCollection()->setOrder('price', 'asc');
}
elseif ($currentOrder == 'mostviewed')
{
$subject->getCollection()->setOrder('mostviewed');
}
}
else
{
$subject->getCollection()->getSelect()->reset('order');
$subject->getCollection()->setOrder('price', 'asc');
}
return $result;
}
}

 

Step 4:

app/code/Wishusucess/SortByPrice/Plugin/Catalog/Model/Config.php

<?php
/*
|--------------------------------------------------------------------------
| Wishsucess SortByPrice Filter
|--------------------------------------------------------------------------
|
| SortByPrice High To Low and Low To High Filter
|
| @author Hemant Singh
| http://www.wishusucess.com/
*/
namespace Wishusucess\SortByPrice\Plugin\Catalog\Model;
class Config
{
public function afterGetAttributeUsedForSortByArray(\Magento\Catalog\Model\Config $catalogConfig,
$results)
{
$results['low_to_high'] = __('Price - Low To High');
$results['high_to_low'] = __('Price - High To Low');
$results['mostviewed'] = __('Recommended');
return $results;
}
}

 

Step 5: Create Attribute High To Low and Low To High and Most Viewed

Now you have to inside of the Magento 2 admin panel and choose Admin=>Stores=>Attribute=>Product=>Add Attribute

And create the following attributes:

  • Low To High
  • High To Low
  • Most viewed

If you have multiple attributes set then you have to add the above attributes in that attributes set otherwise you have to add in the default attribute.

 

Now, Run Following Command:

php bin/magento setup:upgrade

php bin/magento setup:di:compile

php bin/magento setup:static-content:deplpy -f

php bin/magento cache:clean

Magento 2 SortByPrice Filter

 

Conclusion of Sort By Price Filter:

Now we have successfully been able to provide sort options through the above code for Low to High & High to Low and Most viewed product filter. But if you are still facing any kind of issue we are here to help you. Please post your comment here.

 

Download Link:

Wishusucess SortByPrice Filter Magento 2 Extension

 

Related Post:

Wishusucess AdminMenu: How to Create Magento 2 Admin Menu Module

Search AutoComplete: Magento 2 Module Add All Category for Search

 

Recommended Post:

Magento 2.4 Installation Guide: How to Install Magento 2.4.2

Magento Store: Best 36 Magento Websites Example in The World

SEO Packages: How Much Do SEO Packages Cost in India, SEO Pricing

Magento 2 SmartSearch: Best Smart Search Auto Complete Module

Here we are going to learn how we can make our Magento 2 catalog search to a Magento 2 SmartSearch. Wishusucess Smart Search Autocomplete extension gives a better user experience by giving the most relevant search results.

When customers come to your store and try to search for something then it's our responsility to provide products they want and make a purchase.

So this is one of the most important solutions which increase the sales on the store and makes e-commerce store successful.

When customers find the right product when they search that means your usability is increasing and increasing the store usability is also the most important point in any e-commerce store success.

Our Magento 2 expert developer developed the Wishusucess Smart Search Autocomplete which will be very helpful for any store to keep a good customer experiance.

 

Magento 2 SmartSearch AutoComplete Basic File

When we create module like smartsearch in magento then we  need to create some importnt file. Here all the basic files are:

app/code/Wishusucess/SmartSearch/registration.php

app/code/Wishusucess/SmartSearch/etc/module.xml

app/code/Wishusucess/SmartSearch/etc/di.xml

app/code/Wishusucess/SmartSearch/Model/Autocomplete/SearchDataProvider.php

app/code/Wishusucess/SmartSearch/view/frontend/layout/default.xml

app/code/Wishusucess/SmartSearch/view/frontend/templates/form.mini.phtml

app/code/Wishusucess/SmartSearch/view/frontend/requirejs-config.js

app/code/Wishusucess/SmartSearch/view/frontend/web/form-mini.js

app/code/Wishusucess/SmartSearch/view/frontend/web/css/module.less

 

Wishusucess Magento 2 Smart Search Features

  • This SmartSearch module provides the best search experience.
  • Shows relevant product suggestions.
  • Wishuscess SmartSearch also adds Advanced Search Autocomplete.
  • Gives product thumbnail, price, product label, rating, in-stock status in product search suggestion result.
  • It offers the most relevant sort order of products when we go on the search results page.

Magento 2 SmartSearch Module

 

Best Compatibility With Magento 2.3

We have tested it on Magento 2.3 and we get the best result in this Magento version and but this module is quite compatible with Magento 2.1, 2.2, 2.3, and 2.4.

 

Step 1: Register Your SmartSearch

app/code/Wishusucess/SmartSearch/registration.php

<?php
/*
| Registration file for SmartSearch Module
|
| @author Hemant Singh
| @date 23 november 2015
| http://www.wishusucess.com/
*/

\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Wishusucess_SmartSearch',
__DIR__
);

 

Step 2: Give The Basic Information About Your Module

app/code/Wishusucess/SmartSearch/etc/module.xml

<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*
* Author: Hemant Singh
* Website: http://www.wishusucess.com/
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Wishusucess_SmartSearch" setup_version="2.0.0"/>
</config>

 

Step 3: Constructor Arguments

Now we have to configure our class constructor arguments and for that, we have to create di.xml in the argument node.

app/code/Wishusucess/SmartSearch/etc/di.xml

<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*
* Author: Hemant Singh
* Website URL: http://www.wishusucess.com/
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\CatalogSearch\Model\Autocomplete\DataProvider" type="Wishusucess\SmartSearch\Model\Autocomplete\SearchDataProvider" />
</config>

 

Step 4: Data Provider of Magento 2 SmartSearch

This Data Provider class will allow us to define the things once and run them many times with any kinds of inputs at the same time or different times, for checking multiple use cases.

app/code/Wishusucess/SmartSearch/Model/Autocomplete/SearchDataProvider.php

<?php
/*
|--------------------------------------------------------------------------
| Autocomplete SearchDataProvider
|--------------------------------------------------------------------------
|
| Autocomplete
|
| @author Hemant Singh
| http://www.wishusucess.com/
*/
namespace Wishusucess\SmartSearch\Model\Autocomplete;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Helper\Image;
use Magento\Framework\Api\FilterBuilder;
use Magento\Framework\Api\Search\FilterGroupBuilder;
use Magento\Framework\Api\Search\SearchCriteriaFactory as FullTextSearchCriteriaFactory;
use Magento\Framework\Api\Search\SearchInterface as FullTextSearchApi;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Search\Model\Autocomplete\DataProviderInterface;
use Magento\Search\Model\Autocomplete\ItemFactory;
use Magento\Search\Model\QueryFactory;
use Magento\Store\Model\StoreManagerInterface;

/**
* Full text search implementation of autocomplete.
*
* @package Sparx\SmartSearch
* @author Sparx
* @copyright Copyright (c) 2015, Sparx. All rights reserved
*/
class SearchDataProvider implements DataProviderInterface
{
const PRODUCTS_NUMBER_IN_SUGGEST = 7;

/** @var QueryFactory */
protected $queryFactory;

/** @var ItemFactory */
protected $itemFactory;

/** @var \Magento\Framework\Api\Search\SearchInterface */
protected $fullTextSearchApi;

/** @var FullTextSearchCriteriaFactory */
protected $fullTextSearchCriteriaFactory;

/** @var FilterGroupBuilder */
protected $searchFilterGroupBuilder;

/** @var FilterBuilder */
protected $filterBuilder;

/** @var ProductRepositoryInterface */
protected $productRepository;

/** @var SearchCriteriaBuilder */
protected $searchCriteriaBuilder;

/**
* @var StoreManagerInterface
*/
protected $storeManager;

/**
* @var PriceCurrencyInterface
*/
protected $priceCurrency;

/**
* @var ProductHelper
*/
protected $productHelper;

/** @var \Magento\Catalog\Helper\Image */
protected $imageHelper;

/**
* Initialize dependencies.
*
* @param QueryFactory $queryFactory
* @param ItemFactory $itemFactory
* @param FullTextSearchApi $search
* @param FullTextSearchCriteriaFactory $searchCriteriaFactory
* @param FilterGroupBuilder $searchFilterGroupBuilder
* @param FilterBuilder $filterBuilder
* @param ProductRepositoryInterface $productRepository
* @param SearchCriteriaBuilder $searchCriteriaBuilder
* @param StoreManagerInterface $storeManager
* @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
* @param \Magento\Catalog\Helper\Image $imageHelper
*/
public function __construct(
QueryFactory $queryFactory,
ItemFactory $itemFactory,
FullTextSearchApi $search,
FullTextSearchCriteriaFactory $searchCriteriaFactory,
FilterGroupBuilder $searchFilterGroupBuilder,
FilterBuilder $filterBuilder,
ProductRepositoryInterface $productRepository,
SearchCriteriaBuilder $searchCriteriaBuilder,
StoreManagerInterface $storeManager,
PriceCurrencyInterface $priceCurrency,
Image $imageHelper
)
{
$this->queryFactory = $queryFactory;
$this->itemFactory = $itemFactory;
$this->fullTextSearchApi = $search;
$this->fullTextSearchCriteriaFactory = $searchCriteriaFactory;
$this->filterBuilder = $filterBuilder;
$this->searchFilterGroupBuilder = $searchFilterGroupBuilder;
$this->productRepository = $productRepository;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->storeManager = $storeManager;
$this->priceCurrency = $priceCurrency;
$this->imageHelper = $imageHelper;
}

/**
* getItems method
*
* @return array
*/
public function getItems()
{
$result = [ ];
$query = $this->queryFactory->get()->getQueryText();
$productIds = $this->searchProductsFullText($query);

// Check if products are found
if ( $productIds )
{
$searchCriteria = $this->searchCriteriaBuilder->addFilter('entity_id', $productIds, 'in')->create();
$products = $this->productRepository->getList($searchCriteria);

foreach ( $products->getItems() as $product )
{
$childProductimage = array();
$image = $this->imageHelper->init($product, 'product_page_image_small')->getUrl();
$_children = $product->getTypeInstance()->getUsedProducts($product);
foreach ($_children as $child){
$childProductimage[] = $this->imageHelper->init($child, 'product_page_image_small')->getUrl();
}

// if(!$image){
$image = $childProductimage[0];
// }
$resultItem = $this->itemFactory->create([
'type' => $product->getTypeId(),
'title' => $product->getName(),
'price' => $this->priceCurrency->format($product->getPriceInfo()->getPrice('regular_price')->getAmount()->getValue(),false),
'special_price' => $this->priceCurrency->format($product->getPriceInfo()->getPrice('special_price')->getAmount()->getValue(),false),
'has_special_price' => $product->getSpecialPrice() > 0 ? true : false,
'image' => $image,
'url' => $product->getProductUrl()
]);
$result[] = $resultItem;
}
}

return $result;
}

/**
* Perform full text search and find IDs of matching products.
*
* @param $query
*
* @return array
*/
protected function searchProductsFullText($query)
{
$searchCriteria = $this->fullTextSearchCriteriaFactory->create();

/** To get list of available request names see Magento/CatalogSearch/etc/search_request.xml */
$searchCriteria->setRequestName('quick_search_container');
$filter = $this->filterBuilder->setField('search_term')->setValue($query)->setConditionType('like')->create();
$filterGroup = $this->searchFilterGroupBuilder->addFilter($filter)->create();
$currentPage = 1;
$searchCriteria->setFilterGroups([ $filterGroup ])
->setCurrentPage($currentPage)
->setPageSize(self::PRODUCTS_NUMBER_IN_SUGGEST);
$searchResults = $this->fullTextSearchApi->search($searchCriteria);
$productIds = [ ];

/**
* Full text search returns document IDs (in this case product IDs),
* so to get products information we need to load them using filtration by these IDs
*/
foreach ( $searchResults->getItems() as $searchDocument )
{
$productIds[] = $searchDocument->getId();
}

return $productIds;
}
}

 

Step 5: Magento 2 SmartSearch FormMini

Here we can add overrided the form.mini.phtml file in default.xml file.

app/code/Wishusucess/SmartSearch/view/frontend/layout/default.xml

<?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">
<head>
<css src="Sparx_SmartSearch::css/module.css"/>
</head>
<body> 
<referenceContainer name="header-wrapper">
<referenceBlock name="top.search">
<arguments>
<argument name="template" xsi:type="string">Wishusucess/SmartSeach/templates/form.mini.phtml</argument>
</arguments>
</referenceBlock>
</referenceContainer>
</body>
</page>

 

Step 6:

app/code/Wishusucess/SmartSearch/view/frontend/templates/form.mini.phtml

<?php
/*
* Author: Hemant Singh
* Website URL: http://www.wishusucess.com/
*/
$helper = $this->helper('Magento\Search\Helper\Data');
?>
<div class="has-toggle search-sections">

<div class="inner-toggle clearfix">
<div class="block block-search">
<div class="block block-title"><strong><?php echo __('Search'); ?></strong></div>
<div class="block block-content">
<form class="form minisearch" id="search_mini_form" action="<?php echo $helper->getResultUrl() ?>" method="get">
<div class="field search">
<div class="control">
<input id="search"
data-mage-init='{"quickSearch":{
"formSelector":"#search_mini_form",
"url":"<?php echo $this->getUrl('search/ajax/suggest'); ?>",
"destinationSelector":"#search_autocomplete"}
}'
type="text"
name="<?php echo $helper->getQueryParamName() ?>"
value="<?php echo $helper->getEscapedQueryText() ?>"
placeholder="<?php echo __('Search entire store here...'); ?>"
class="input-text"
autocomplete="off"
onfocus=this.value=''/>
<div id="search_autocomplete" class="search-autocomplete"></div>

<?php echo $this->getChildHtml() ?>
</div>
<!-- .control -->

<button type="submit" value="Zoeken" class="btn btn-search"><?php echo __('Search'); ?></button>

</div> <!-- .field .search -->
<div class="actions"></div>
</form>
</div>
<!-- .block-content -->
</div>
<!-- .block-search -->
</div>
<!-- .inner-toggle -->
</div>
<!-- .search-sections -->

 

Step 7:

app/code/Wishusucess/SmartSearch/view/frontend/requirejs-config.js

var config = {
map: {
'*': {
'quickSearch':'Wishusucess_SmartSearch/form-mini'
}
}
};

 

Step 8:

app/code/Wishusucess/SmartSearch/view/frontend/web/form-mini.js

/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
/*jshint browser:true jquery:true*/
define([
'jquery',
'underscore',
'mage/template',
'jquery/ui',
'mage/translate'
], function ($, _, mageTemplate) {
'use strict';

/**
* Check wether the incoming string is not empty or if doesn't consist of spaces.
*
* @param {String} value - Value to check.
* @returns {Boolean}
*/
function isEmpty(value) {
return (value.length === 0) || (value == null) || /^\s+$/.test(value);
}

$.widget('mage.quickSearch', {
options: {
autocomplete: 'off',
minSearchLength: 3,
responseFieldElements: 'ul li',
selectClass: 'selected',
template:
'<div class="c-smartsearch__product col-8-8">' +

'<a class="c-smartsearch__image col-2-8" href="<%- data.url %>">' +
'<img src="<%- data.image %>">' +
'</a>' +

'<div class="c-smartsearch__description col-6-8 last">' +

'<a class="c-smartsearch__title h4" href="<%- data.url %>">' +
'<%- data.title %>' +
'</a>' +

'<div class="c-smartsearch__price">' +
'<span>' + $.mage.__("") + ' <span class="<% if (data.has_special_price) { %> u-strike-through <% } %> ">' + '<%- data.price %></span></span>' +
'</div>' +

'<% if (data.has_special_price) { %>' +
'<div class="c-smartsearch__sale">' +
'<span class="c-smartsearch__sale--accent"> <%- data.special_price %></span>' +
'</div>' +
'<% } %>'
+
'</div> <!-- .c-smartsearch__product col-8-8 -->'
,
submitBtn: 'button[type="submit"]',
searchLabel: '[data-role=minisearch-label]'
},
_create: function () {
this.responseList = {
indexList: null,
selected: null
};
this.autoComplete = $(this.options.destinationSelector);
this.searchForm = $(this.options.formSelector);
this.submitBtn = this.searchForm.find(this.options.submitBtn)[0];
this.searchLabel = $(this.options.searchLabel);

_.bindAll(this, '_onKeyDown', '_onPropertyChange', '_onSubmit');

this.submitBtn.disabled = true;

this.element.attr('autocomplete', this.options.autocomplete);

this.element.on('blur', $.proxy(function () {

setTimeout($.proxy(function () {
if (this.autoComplete.is(':hidden')) {
this.searchLabel.removeClass('active');
}
this.autoComplete.hide();
this._updateAriaHasPopup(false);
}, this), 250);
}, this));

this.element.trigger('blur');

this.element.on('focus', $.proxy(function () {
this.searchLabel.addClass('active');

if($('#search').val().length >= 3) {
$('#search_autocomplete').css('display', 'block');
}
}, this));
this.element.on('keydown', this._onKeyDown);
this.element.on('input propertychange', this._onPropertyChange);

this.searchForm.on('submit', $.proxy(function() {
this._onSubmit();
this._updateAriaHasPopup(false);
}, this));
},
/**
* @private
* @return {Element} The first element in the suggestion list.
*/
_getFirstVisibleElement: function () {
return this.responseList.indexList ? this.responseList.indexList.first() : false;
},

/**
* @private
* @return {Element} The last element in the suggestion list.
*/
_getLastElement: function () {
return this.responseList.indexList ? this.responseList.indexList.last() : false;
},

/**
* @private
* @param {Boolean} show Set attribute aria-haspopup to "true/false" for element.
*/
_updateAriaHasPopup: function(show) {
if (show) {
this.element.attr('aria-haspopup', 'true');
} else {
this.element.attr('aria-haspopup', 'false');
}
},

/**
* Clears the item selected from the suggestion list and resets the suggestion list.
* @private
* @param {Boolean} all - Controls whether to clear the suggestion list.
*/
_resetResponseList: function (all) {
this.responseList.selected = null;

if (all === true) {
this.responseList.indexList = null;
}
},

/**
* Executes when the search box is submitted. Sets the search input field to the
* value of the selected item.
* @private
* @param {Event} e - The submit event
*/
_onSubmit: function (e) {
var value = this.element.val();

if (isEmpty(value)) {
e.preventDefault();
}

if (this.responseList.selected) {
this.element.val(this.responseList.selected.find('.qs-option-name').text());
}
},

/**
* Executes when keys are pressed in the search input field. Performs specific actions
* depending on which keys are pressed.
* @private
* @param {Event} e - The key down event
* @return {Boolean} Default return type for any unhandled keys
*/
_onKeyDown: function (e) {
var keyCode = e.keyCode || e.which;

switch (keyCode) {
case $.ui.keyCode.HOME:
// $('#search').removeClass('loading');
this._getFirstVisibleElement().addClass(this.options.selectClass);
this.responseList.selected = this._getFirstVisibleElement();
break;
case $.ui.keyCode.END:
// $('#search').removeClass('loading');
this._getLastElement().addClass(this.options.selectClass);
this.responseList.selected = this._getLastElement();
break;
case $.ui.keyCode.ESCAPE:
this._resetResponseList(true);
// $('#search').removeClass('loading');
this.autoComplete.hide();
break;
case $.ui.keyCode.ENTER:
// $('#search').removeClass('loading');
this.searchForm.trigger('submit');
break;
case $.ui.keyCode.DOWN:

if (this.responseList.indexList) {
if (!this.responseList.selected) {
this._getFirstVisibleElement().addClass(this.options.selectClass);
this.responseList.selected = this._getFirstVisibleElement();
}
else if (!this._getLastElement().hasClass(this.options.selectClass)) {
this.responseList.selected = this.responseList.selected.removeClass(this.options.selectClass).next().addClass(this.options.selectClass);
} else {
this.responseList.selected.removeClass(this.options.selectClass);
this._getFirstVisibleElement().addClass(this.options.selectClass);
this.responseList.selected = this._getFirstVisibleElement();
}
this.element.val(this.responseList.selected.find('.qs-option-name').text());
this.element.attr('aria-activedescendant', this.responseList.selected.attr('id'));
}
break;
case $.ui.keyCode.UP:

if (this.responseList.indexList !== null) {
if (!this._getFirstVisibleElement().hasClass(this.options.selectClass)) {
this.responseList.selected = this.responseList.selected.removeClass(this.options.selectClass).prev().addClass(this.options.selectClass);

} else {
this.responseList.selected.removeClass(this.options.selectClass);
this._getLastElement().addClass(this.options.selectClass);
this.responseList.selected = this._getLastElement();
}
this.element.val(this.responseList.selected.find('.qs-option-name').text());
this.element.attr('aria-activedescendant', this.responseList.selected.attr('id'));
}
break;
default:
return true;
}
},

/**
* Executes when the value of the search input field changes. Executes a GET request
* to populate a suggestion list based on entered text. Handles click (select), hover,
* and mouseout events on the populated suggestion list dropdown.
* @private
*/
_onPropertyChange: function () {
var searchField = this.element,
clonePosition = {
position: 'absolute',
width: '100%'
// Removed to fix display issues
// left: searchField.offset().left,
// top: searchField.offset().top + searchField.outerHeight(),
//width: searchField.outerWidth()
},
source = this.options.template,
template = mageTemplate(source),
dropdown = $('<div class="c-smartsearch"><div class="c-smartsearch__overlay"></div><div class="c-smartsearch__wrapper"><div class="c-smartsearch__wrapper--inner"><div class="c-smartsearch__content clearfix"></div>'),
value = this.element.val();

this.submitBtn.disabled = isEmpty(value);

if (value.length >= parseInt(this.options.minSearchLength, 10)) {

$('#search_mini_form').addClass('is-loading');

if(this.request) {
this.request.abort();
}

this.request = $.get(this.options.url, {q: value}, $.proxy(function (data) {

// Check if SmartSearch returned results
if( ! data.length)
dropdown.find('.c-smartsearch__content').append('<div class="c-smartsearch__product col-8-8">' + $.mage.__('No products found.') + '</div>');

$.each(data, function(index, element) {
element.index = index;

var html = template({
data: element
});
dropdown.find('.c-smartsearch__content').append(html);
});

this.responseList.indexList = this.autoComplete.html(dropdown)
.css(clonePosition)
.show()
.find(this.options.responseFieldElements + ':visible');

$('#search_mini_form').removeClass('is-loading');

this._resetResponseList(false);
this.element.removeAttr('aria-activedescendant');

if (this.responseList.indexList.length) {
this._updateAriaHasPopup(true);
} else {
this._updateAriaHasPopup(false);
}

this.responseList.indexList
.on('click', function (e) {
this.responseList.selected = $(e.target);
this.searchForm.trigger('submit');
}.bind(this))
.on('mouseenter mouseleave', function (e) {
this.responseList.indexList.removeClass(this.options.selectClass);
$(e.target).addClass(this.options.selectClass);
this.responseList.selected = $(e.target);
this.element.attr('aria-activedescendant', $(e.target).attr('id'));
}.bind(this))
.on('mouseout', function (e) {
if (!this._getLastElement() && this._getLastElement().hasClass(this.options.selectClass)) {
$(e.target).removeClass(this.options.selectClass);
this._resetResponseList(false);
}
}.bind(this));
}, this));
} else {
this._resetResponseList(true);
this.autoComplete.hide();
this._updateAriaHasPopup(false);
this.element.removeAttr('aria-activedescendant');
}
}
});

return $.mage.quickSearch;
});

 

Step 9:

Now design your Magento 2 catalog search box and how that content should appear.

app/code/Wishusucess/SmartSearch/view/frontend/web/css/module.less

/** ================================================================
* Author: Hemant Singh
* Website URL: http://www.wishusucess.com/
* ============================================================= */
#search.loading {

}
#search_autocomplete {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: visible;
}
.c-smartsearch {
text-transform: capitalize;
}
.c-smartsearch__overlay {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 998;
}
.c-smartsearch__wrapper {
position: absolute;
width: 99.6%;
top: 32px;
z-index: 999;
left: 7px;
border: 1px solid #ededed;
box-shadow: 0px 1px 4px 0px #ededed;
background: #FFFFFF;
}
.c-smartsearch__wrapper--inner {
width: 100%;
max-width: 460px;
margin: 0 auto;
}
.c-smartsearch__content {
background-color: white;
}
.c-smartsearch__product {
border-top: 1px solid #f2f2f2;
padding: 15px 15px;
}
.c-smartsearch__title {
text-decoration: none;
float: left;
clear: both;
}
.c-smartsearch {
.c-smartsearch__sale--accent {
color: #3a3a3a;
}
.c-smartsearch__price {
float: left;

> span {
padding-right: 2px;
}
}
.u-strike-through {
text-decoration: line-through;
}
.col-8-8 {
width: 89%;
float: left;
margin-left: 0;
margin-right: 0;
}
.col-2-8 {
width: 22.89157%;
float: left;
margin-right: 2.81124%;
}
.col-6-8 {
width: 72%;
float: right;
margin-right: 0;
margin-top: -4px;
}
}

@media screen and (max-width: 1023px) {
.c-smartsearch__wrapper--inner {
max-width: 100% !important;
}

.c-smartsearch__wrapper {
top: 50px !important;
}

.c-smartsearch__image {
text-align: center;

img {
max-height: 150px;
width: auto;
}
}
}

 

Now, Run Following Command:

php bin/magento setup:upgrade

php bin/magento setup:di:compile

php bin/magento setup:static-content:deplpy -f

php bin/magento cache:clean

 

Download Link:

Wishusucess Smart Search Magento 2 Extension

 

Related Post:

Wishusucess AdminMenu: How to Create Magento 2 Admin Menu Module

Search AutoComplete: Magento 2 Module Add All Category for Search

 

Recommended Post:

Magento 2.4 Installation Guide: How to Install Magento 2.4.2

Magento Store: Best 36 Magento Websites Example in The World

Search AutoComplete: Magento 2 Module Add All Category for Search

This article is all about how we can develop a Search AutoComplete extension in Magento 2. This module also provides the options to enable category search facilities.

When you install this module this automatically created a div box on the left side of the Magento 2 catalog search box in the header content and then you can select a category from the dropdown and search the product based on category.

Wishusucess Search AutoComplete

 

Wishusucess Search AutoComplete Features:

  • Easy to install/manage
  • Get all the category list
  • Enable/disable to search from categories
  • You can set the number of categories to display
  • Define the search delay period

Wishusucess Search AutoComplete

 

Step 1:

app/code/Wishusucess/SearchAutocomplete/registration.php

<?php
/*
Author: Wishusucess
Developer: Hemant Singh
Website URL: http://www.wishusucess.com/
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Wishusucess_SearchAutocomplete',
__DIR__
);

 

Step 2:

app/code/Wishusucess/SearchAutocomplete/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="Wishusucess_SearchAutocomplete" setup_version="1.0.0">
</module>
</config>

 

Step 3:

app/code/Wishusucess/SearchAutocomplete/frontend/routes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="searchautocomplete" frontName="searchautocomplete">
<module name="Wishusucess_SearchAutocomplete" />
</route>
</router>
</config>

 

Step 4: Magento 2 Search AutoComplete Controller

 

app/code/Wishusucess/SearchAutocomplete/Controller/Index/Index.php

<?php
/*
Author: Wishusucess
Developer: Hemant Singh
Website URL: http://www.wishusucess.com/
*/
namespace Wishusucess\SearchAutocomplete\Controller\Index;

class Index extends \Magento\Framework\App\Action\Action
{
protected $_resultJsonFactory; 
protected $_productCollectionFactory;
protected $_reviewFactory;
protected $_storeManager;
protected $_imageBuilder;
protected $_productVisibility;
protected $_categoryFactory;
protected $_priceHelper;

public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
\Magento\Review\Model\ReviewFactory $reviewFactory,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Catalog\Block\Product\ImageBuilder $imageBuilder,
\Magento\Catalog\Model\Product\Visibility $productVisibility,
\Magento\Catalog\Model\CategoryFactory $categoryFactory,
\Magento\Framework\Pricing\Helper\Data $priceHelper)
{
$this->_resultJsonFactory = $resultJsonFactory;
$this->_productCollectionFactory = $productCollectionFactory;
$this->_reviewFactory = $reviewFactory;
$this->_storeManager = $storeManager;
$this->_imageBuilder = $imageBuilder;
$this->_productVisibility = $productVisibility;
$this->_categoryFactory = $categoryFactory;
$this->_priceHelper = $priceHelper;
parent::__construct($context);
}
public function execute()
{
$postMessage = $this->getRequest()->getPost();

$query = preg_replace('/[^A-Za-z0-9\ \_\'\-]/', '', $postMessage['query']);
$category = preg_replace('/[^a-z0-9]/', '', $postMessage['category']);


if($category=='all'){
$collection = $this->_productCollectionFactory->create()
->addAttributeToSelect('*')
->addAttributeToFilter('name', array('like'=>'%'.$query.'%'));
}else{
$collection = $this->getProductCollection($category);
$collection->addAttributeToFilter('name', array('like'=>'%'.$query.'%'));
}
$collection->setVisibility($this->_productVisibility->getVisibleInSiteIds());

$collection ->setPageSize(5)
->setCurPage(1);

$productList = [];
$i = 1;

foreach ($collection as $product) {
$productList[$i]['name'] = str_ireplace($query,'<b>'.$query.'</b>',$product->getName());
$productList[$i]['price'] = $this->_priceHelper->currency(number_format($product->getFinalPrice(),2),true,false);
$productList[$i]['url'] = $product->getProductUrl();
$productList[$i]['thumbnail'] = $this->getImage($product, 'category_page_list')->getImageUrl();
$this->_reviewFactory->create()->getEntitySummary($product, $this->_storeManager->getStore()->getId());
$productList[$i]['rating'] = $product->getRatingSummary()->getRatingSummary();
$i++;
}

if($collection->getSize() > 0){
return $this->_resultJsonFactory->create()->setData($productList);
}else{
return $this->_resultJsonFactory->create()->setData([]);
}
}
public function getImage($product, $imageId)
{
return $this->_imageBuilder->setProduct($product)
->setImageId($imageId)
->create();
}
public function getCategory($categoryId)
{
$category = $this->_categoryFactory->create()->load($categoryId);
return $category;
}
public function getProductCollection($categoryId)
{
return $this->getCategory($categoryId)->getProductCollection()->addAttributeToSelect('*'); 
}
}

 

Step 5: Create Block for Search AutoComplete

app/code/Wishusucess/SearchAutocomplete/Block/SearchAutocomplete.php

<?php
/*
Author: Wishusucess
Developer: Hemant Singh
Website URL: http://www.wishusucess.com/
*/
namespace Wishusucess\SearchAutocomplete\Block;
class SearchAutocomplete extends \Magento\Framework\View\Element\Template
{
protected $_categoryCollectionFactory;
protected $_storeManager;
protected $_store;
protected $_categoryRepository;

public function __construct(
\Magento\Backend\Block\Template\Context $context, 
\Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Store\Model\Store $store,
\Magento\Catalog\Model\CategoryRepository $categoryRepository,
array $data = []
)
{
$this->_categoryCollectionFactory = $categoryCollectionFactory;
$this->_storeManager = $storeManager;
$this->_store = $store;
$this->_categoryRepository = $categoryRepository;
parent::__construct($context, $data);
}

public function getCategoryCollection($isActive = true, $level = false, $sortBy = false, $pageSize = false)
{
$collection = $this->_categoryCollectionFactory->create();
$collection->addAttributeToSelect('*');
if ($isActive) {
$collection->addIsActiveFilter();
}
if ($level) {
$collection->addLevelFilter($level);
}
if ($sortBy) {
$collection->addOrderField($sortBy);
}
if ($pageSize) {
$collection->setPageSize($pageSize); 
}
$collection->setOrder('position', 'ASC');
return $collection;
}
public function getAjaxUrl(){
return $this->_storeManager->getStore()->getUrl('searchautocomplete/index/index');
}
public function getMediaUrl(){
return $this ->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA );
}
public function getRootCategoryId()
{
return $this->_store->getStoreRootCategoryId();
}
public function getCategories(){
return $this->_categoryRepository->get(2)->getChildrenCategories();
}
}

 

Step 6:

app/code/Wishusucess/SearchAutocomplete/view/frontend/layout/default.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd" >
<body>
<referenceContainer name="header-wrapper">
<referenceBlock name="top.search" remove="true"/>
<block class="Magento\Framework\View\Element\Template" name="top.search" as="" template="Magento_Search::form.mini.phtml" />
<block class="Wishusucess\SearchAutocomplete\Block\SearchAutocomplete" name="search.autocomplete" after="logo" template="search/autocomplete.phtml" />
</referenceContainer>
</body>
</page>

 

Step 7:

app/code/Wishusucess/SearchAutocomplete/templates/search/autocomplete.phtml

<?php
/*
Author: Wishusucess
Developer: Hemant Singh
Website URL: http://www.wishusucess.com/
*/
// @codingStandardsIgnoreFile
?>
<?php
/** @var $block \Magento\Framework\View\Element\Template */
/** @var $helper \Magento\Search\Helper\Data */
$helper = $this->helper(\Magento\Search\Helper\Data::class);
?>
<div class="block block-search">
<div class="block block-title"><strong><?= /* @escapeNotVerified */ __('Search') ?></strong></div>
<div class="block block-content">
<form class="form minisearch" id="search_mini_form" action="<?= /* @escapeNotVerified */ $helper->getResultUrl() ?>" method="get">
<div class="field search">
<label class="label" for="search" data-role="minisearch-label">
<span><?= /* @escapeNotVerified */ __('Search') ?></span>
</label>
<div class="control">
<div id="searchCategories">
<select>
<option value="all">All Categories</option>
<?php 
foreach($this->getCategories() as $category){
?>
<option value="<?php echo $category->getId(); ?>"><?php echo $category->getName(); ?></option>
<?php 
}
?>
</select>
</div>
<input id="search"
type="text"
name="<?= /* @escapeNotVerified */ $helper->getQueryParamName() ?>"
value="<?= /* @escapeNotVerified */ $helper->getEscapedQueryText() ?>"
placeholder="<?= /* @escapeNotVerified */ __('Search entire store here...') ?>"
class="input-text"
maxlength="<?= /* @escapeNotVerified */ $helper->getMaxQueryLength() ?>"
autocomplete="off"/>
</div>
</div>
<div class="actions">
<button type="submit"
title="<?= $block->escapeHtml(__('Search')) ?>"
class="action search">
<span><?= /* @escapeNotVerified */ __('Search') ?></span>
</button>
</div>
</form>
</div>
</div>

<script type="text/javascript">
require(['jquery', 'domReady!'], function($){
var searchControlElement = $('#search_mini_form .field.search .control').first();
searchControlElement.append('<div id="searchAutocomplete" style="display:none;"><ul></ul><button type="submit"><?= /* @escapeNotVerified */ __('View All Results') ?></button></div>');
$('#search_autocomplete').remove();
$('#search').unbind();
$(window).click(function() {
$('#searchAutocomplete').hide();
});
$('.block.block-search').click(function(event){
event.stopPropagation();
});
$('#search').bind('input', function(){
var searchInput = $(this);
var searchInputValue = searchInput.val().replace("/^[a-zA-Z0-9 _-]+$/i", "");
if(searchInputValue.length >=3){
url = "<?php echo $this->getAjaxUrl(); ?>";
$.ajax({
type: "POST",
url: url,
data: {query: searchInputValue, category: $('#searchCategories select').first().val()},
success: function(data){
console.log(data);
var searchResultHtml = '';
var size = Object.keys(data).length;
for(let i=1; i<=size; i++){
searchResultHtml += '<li data-url="'+data[i]['url']+'">';
searchResultHtml += '<div class="sa-image"><img src="'+data[i]['thumbnail']+'"></div>';
searchResultHtml += '<div class="sa-prop">';
searchResultHtml += '<div class="sa-title"><p>'+data[i]['name']+'</p></div>';
if(data[i]['rating']){
searchResultHtml += '<div class="sa-rating"><div class="rating-summary"><div class="rating-result" title="'+data[i]['rating']+'%"><span style="width:'+data[i]['rating']+'%"><span>'+data[i]['rating']+'%</span></span></div></div></div>';
}
searchResultHtml += '<div class="sa-price"><p>'+data[i]['price']+'<p></div>';
searchResultHtml += '</div>';
searchResultHtml += '</li>';
$('#searchAutocomplete ul').first().html(searchResultHtml);
}
$( "#searchAutocomplete ul li" ).on( "click", function() {
window.location = $(this).data('url');
});
if(size > 0){
$('#searchAutocomplete').show();
}else{
$('#searchAutocomplete').hide();
}
},
error: function (data) {
console.log(data);
}
});
}else{
$('#searchAutocomplete').hide();
}
});
$("#search").on("focus", function(){
var searchInput = $(this);
var searchInputValue = searchInput.val().replace("/^[a-zA-Z0-9 _-]+$/i", "");
if(searchInputValue.length >=3){
url = "<?php echo $this->getAjaxUrl(); ?>";
$.ajax({
type: "POST",
url: url,
data: {query: searchInputValue, category: $('#searchCategories select').first().val()},
success: function(data){
console.log(data);
var searchResultHtml = '';
var size = Object.keys(data).length;
for(let i=1; i<=size; i++){
searchResultHtml += '<li data-url="'+data[i]['url']+'">';
searchResultHtml += '<div class="sa-image"><img src="'+data[i]['thumbnail']+'"></div>';
searchResultHtml += '<div class="sa-prop">';
searchResultHtml += '<div class="sa-title"><p>'+data[i]['name']+'</p></div>';
if(data[i]['rating']){
searchResultHtml += '<div class="sa-rating"><div class="rating-summary"><div class="rating-result" title="'+data[i]['rating']+'%"><span style="width:'+data[i]['rating']+'%"><span>'+data[i]['rating']+'%</span></span></div></div></div>';
}
searchResultHtml += '<div class="sa-price"><p>'+data[i]['price']+'<p></div>';
searchResultHtml += '</div>';
searchResultHtml += '</li>';
$('#searchAutocomplete ul').first().html(searchResultHtml);
}
if(size > 0){
$('#searchAutocomplete').show();
}else{
$('#searchAutocomplete').hide();
}
$( "#searchAutocomplete ul li" ).on( "click", function() {
window.location = $(this).data('url');
});
},
error: function (data) {
console.log(data);
}
});
}else{
$('#searchAutocomplete').hide();
}
});
$("#searchCategories select").first().on("change", function(){
var searchInput = $('#search');
var searchInputValue = searchInput.val().replace("/^[a-zA-Z0-9 _-]+$/i", "");
if(searchInputValue.length >=3){
url = "<?php echo $this->getAjaxUrl(); ?>";
$.ajax({
type: "POST",
url: url,
data: {query: searchInputValue, category: $('#searchCategories select').first().val()},
success: function(data){
console.log(data);
var searchResultHtml = '';
var size = Object.keys(data).length;
for(let i=1; i<=size; i++){
searchResultHtml += '<li data-url="'+data[i]['url']+'">';
searchResultHtml += '<div class="sa-image"><img src="'+data[i]['thumbnail']+'"></div>';
searchResultHtml += '<div class="sa-prop">';
searchResultHtml += '<div class="sa-title"><p>'+data[i]['name']+'</p></div>';
if(data[i]['rating']){
searchResultHtml += '<div class="sa-rating"><div class="rating-summary"><div class="rating-result" title="'+data[i]['rating']+'%"><span style="width:'+data[i]['rating']+'%"><span>'+data[i]['rating']+'%</span></span></div></div></div>';
}
searchResultHtml += '<div class="sa-price"><p>'+data[i]['price']+'<p></div>';
searchResultHtml += '</div>';
searchResultHtml += '</li>';
$('#searchAutocomplete ul').first().html(searchResultHtml);
}
if(size > 0){
$('#searchAutocomplete').show();
}else{
$('#searchAutocomplete').hide();
}
$( "#searchAutocomplete ul li" ).on( "click", function() {
window.location = $(this).data('url');
});
},
error: function (data) {
console.log(data);
}
});
}else{
$('#searchAutocomplete').hide();
}
});
});
</script>
<style type="text/css">
#searchCategories {
display: inline-block;
float: left;
width: 30%;
}
#search {
display: inline-block;
position: relative;
left: unset;
width: 70%;
float: right;
}
.block-search {

}
#searchAutocomplete {
position: absolute;
top: 32px;
border: 1px solid #cccccc;
background-color: white;
width: 100%;
}
#searchAutocomplete button {
margin: 10px;
}
#searchAutocomplete ul {
margin: 0;
padding: 5px;
list-style: none;
}
#searchAutocomplete ul li {
padding: 4px;
border-bottom: 1px solid #cccccc;
margin: 0;
cursor: pointer;
}
#searchAutocomplete ul li:hover, #searchAutocomplete ul li:last-child:hover {
border: 1px solid #cccccc;
}
#searchAutocomplete ul li:last-child {
border-bottom: unset;
}
#searchAutocomplete .sa-image {
display: inline-block;
max-width: 30%;
}
#searchAutocomplete .sa-rating {
margin-top: 10px;
}
#searchAutocomplete .sa-prop {
display: inline-block;
width: 70%;
float: right;
}
#searchAutocomplete .sa-title {
margin-top: 10px;
}
#searchAutocomplete .sa-price {
margin-top: 10px;
padding: 10px;
}
@media all and (min-width: 768px), print {
.block-search {
width: 400px;
padding-left: 0;
}
}
</style>

 

Now, Run Following Command:

php bin/magento setup:upgrade

php bin/magento setup:di:compile

php bin/magento setup:static-content:deplpy -f

php bin/magento cache:clean

 

Search AutoComplete Wishusucess

Download Link

This Extension available on GitHub

 

Related Post:

Wishusucess AdminMenu: How to Create Magento 2 Admin Menu Module

HelloWorld Extension: How to Create Hello World Module

 

Recommended Post:

Magento 2.4 Installation Guide: How to Install Magento 2.4.2

Magento Store: Best 36 Magento Websites Example in The World

Add Custom Wishlist Button in Header Content in Magento 2

If you are looking for customization of the Magento 2 header content then you are on the right page. In this article, I am going to explain how we can add Custom Wishlist Button in the Magento 2 header content.

This button will add before the mini cart button in the top header bar so our order will be look something like catalog search, Wishlist, mini cart links in header content, now read all the files for what's the proper code to add that.

Custom Add To Wishlist Button
Custom Add To Wishlist Button

 

Magento 2 Add Custom Wishlist Button in Header Content

So we have to create a minimum of four files to add a custom wishlist button in header content

app/code/Wishusucess/CustomWishlist/registration.php

app/code/Wishusucess/CustomWishlist/etc/module.xml

app/code/Wishusucess/CustomWishlist/view/frontend/layout/default.xml

app/code/Wishusucess/CustomWishlist/templates/link.phtml

 

Step 1:

Now first we have to register our module so we have created a file which is registration.php

app/code/Wishusucess/CustomWishlist/registration.php

<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/

\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Wishusucess_CustomWishlist',
__DIR__
);

 

Step 2:

Now we have to create a file for module information which is module.xml

app/code/Wishusucess/CustomWishlist/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
<module name="Wishusucess_CustomWishlist" setup_version="1.0.0" />
</config>

 

Step 3: Add Custom Wishlist Button

We have to create a default.xml file and through this layout XML, we can add and remove view elements and their data so we will add wishlist content here.

app/code/Wishusucess/CustomWishlist/view/frontend/layout/default.xml

<?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="header-wrapper">
<block class="Magento\Wishlist\Block\Link" name="wish-list-link-custom" after="minicart" template="Wishusucess_CustomWishlist::link.phtml" />
</referenceContainer>
</body>
</page>

 

Step 4: Add Templates File

Here you can style your button as per your requirement.

app/code/Wishusucess/CustomWishlist/templates/link.phtml

<?php
/* you can customize the wishlist here */
?>
<style>
.custom.link.wishlist{
float: right;
}
.custom.link.wishlist .counter.qty {
background: #ff5501;
color: #fff;
height: 24px;
line-height: 24px;
border-radius: 2px;
display: inline-block;
margin: 3px 0 0;
min-width: 18px;
overflow: hidden;
padding: 0 3px;
text-align: center;
white-space: normal;
}

.wishlist-custom:before {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-size: 22px;
line-height: 28px;
color: #757575;
content: '\e600';
font-family: 'luma-icons';
margin: 0;
vertical-align: top;
display: inline-block;
font-weight: normal;
overflow: hidden;
speak: none;
text-align: center;
}

.wishlist-custom .text{
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
</style>
<div class="custom link wishlist" data-bind="scope: 'wishlist'">
<a <?= /* @noEscape */ $block->getLinkAttributes() ?> class="wishlist-custom">
<span class="text"><?= $block->escapeHtml($block->getLabel()) ?></span>
<!-- ko if: wishlist().counter -->
<span data-bind="text: wishlist().counter" class="counter qty"></span>
<!-- /ko -->
</a>
</div>
<script type="text/x-magento-init">
{
"*": {
"Magento_Ui/js/core/app": {
"components": {
"wishlist": {
"component": "Magento_Wishlist/js/view/wishlist"
}
}
}
}
}

</script>

 

Now Run The Following Command to See Wishusucess Wish List Button:

php bin/magento setup:upgrade

php bin/magento setup:di:compile

php bin/magento setup:static-content:deplpy -f

php bin/magento cache:clean

 

Download This Extension:

GitHub

 

Related Post:

Wishusucess AdminMenu: How to Create Magento 2 Admin Menu Module

HelloWorld Extension: How to Create Hello World Module

 

Recommended Post:

Magento 2.4 Installation Guide: How to Install Magento 2.4.2

Magento Store: Best 36 Magento Websites Example in The World

Create Custom Yes/No Category Attributes in Magento 2

Here, In this post, you will understand how we can add Magento 2 custom category attributes programmatically (InstallSchema.php).

When we develop an online store in Magento 2 then sometimes we need this kind of functionality to add Category Attributes Programmatically.

We have developed a Magento 2 extension so that you can work on a custom Magento 2 module for custom yes/no attributes.

Just download that module or copy each and every file in your app/code and change your attribute title "Title Name" as per your requirements.

We have created two files which are InstallScheme.php and the second file is category_form.xml.

You can do copying and pasting the following snippets in your module. And the snippets that you can achieve immediately.

Add Category Attribute Programmatically in Magento 2

In this article, we will use the Wishusuces Yes No Custom Category Attributes module to learn how to add a category attribute.

Custom Category Attributes

 

Basic File for Yes/No Attribute in Magento 2

We have to create a minimum of four files to get the yes/no attribute in the category section in Magento 2.

Wishusucess/YesnoCustomCategoryAttributes/registration.php

Wishusucess/YesnoCustomCategoryAttributes/etc/module.xml

Wishusucess/YesnoCustomCategoryAttributes/Setup/InstallData.php

Wishusucess/YesnoCustomCategoryAttributes/view/adminhtml/ui_component/category_form.xml

 

Now we will check what content we need to add to all those files

app/code/Wishusucess/YesnoCustomCategoryAttributes/registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Wishusucess_YesnoCustomCategoryAttributes',
__DIR__
);

 

Now we have to create a module.xml file.

Wishusucess/YesnoCustomCategoryAttributes/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="Wishusucess_YesnoCustomCategoryAttributes" setup_version="1.0.0">
</module>
</config>

 

InstallSchema.php for Yes/No Custom Category Attributes

app/code/Wishusucess/YesnoCustomCategoryAttributes/Setup/InstallData.php

<?php
namespace Wishusucess\YesnoCustomCategoryAttributes\Setup;

use Magento\Framework\Setup\{
ModuleContextInterface,
ModuleDataSetupInterface,
InstallDataInterface
};

use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;

class InstallData implements InstallDataInterface
{
private $eavSetupFactory;

public function __construct(EavSetupFactory $eavSetupFactory) {
$this->eavSetupFactory = $eavSetupFactory;
}

public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$eavSetup->addAttribute(\Magento\Catalog\Model\Category::ENTITY, 'custom_category_attributes', [
'type' => 'int',
'label' => 'Custom Category Attributes',
'input' => 'boolean',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'visible' => true,
'default' => '0',
'required' => false,
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
'group' => 'Display Settings',
]);
}
}

 

How To Display The Custom Category Attributes

Magento 2 category_form.xml provides the options to add custom attributes in the category section. So here view/adminhtml/UI Component is rendered with configuration from the category_form.xml file.

All files with that name are merged together. As a result, We will add a field by creating a category_form.xml file in the

So here we have added these custom attributes in the category display setting.

These custom_category_attributes should match the ID of the attribute with InstallSchema.php.

app/code/Wishusucess/YesnoCustomCategoryAttributes/view/adminhtml/ui_component/category_form.xml

<?xml version="1.0"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<fieldset name="display_settings">
<field name="custom_category_attributes">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">boolean</item>
<item name="formElement" xsi:type="string">checkbox</item>
<item name="label" xsi:type="string" translate="true">Custom Category Attributes</item>
<item name="prefer" xsi:type="string">toggle</item>
<item name="valueMap" xsi:type="array">
<item name="true" xsi:type="string">1</item>
<item name="false" xsi:type="string">0</item>
</item>
<item name="default" xsi:type="number">0</item>
</item>
</argument>
</field>
</fieldset>
</form>

 

Download Yes/No Category Custom Attributes

On Github: Wishusucess/YesnoCustomCategoryAttributes

 

Related Post:

HelloWorld Extension: How to Create Hello World Module

Wishusucess AdminMenu: How to Create Magento 2 Admin Menu Module

 

Recommended Post:

Magento 2.4 Installation Guide: How to Install Magento 2.4.2

Magento Store: Best 36 Magento Websites Example in The World