1

I'm trying to create some type of search method for customers where they select the product's brand they want to search and then, if they want, they can also select the category they want (if there are products from that brand in that category).

enter image description here

As you can see in the above image first we select brand, then we get that category dropdownlist all the categories (which have products), for that brand.

I'm doing this with 2 DropDownLists:

<div style="padding:30px 0 15px;">
  <div class="container">
    <div class="slider-with-side" style="margin: 0 -15px;">
      <div class="slider-area" style="padding:0 15px;">
        <div id="banner-slider-demo-7" class="owl-carousel owl-bottom-narrow owl-banner-carousel">
            <div class="item">
                <img src="" alt="" style="width: 100%;" />
            </div>
            <div class="item">
                <img src="" alt="" style="width: 100%;" />
            </div>
        </div>
      </div>
      <div class="side-area" style="padding:0 15px;">
        <div class="form-find-area theme-border-color">
          <h3 class="form-title">Pesquisar</h3>
          <form action="#" class="form-find">
    <select name="home_manufacturers">
        <option value="">Brand</option>
                <option value="44" data-href="/catalogo?manufacturer=44">Dell</option>
                <option value="51" data-href="/catalogo?manufacturer=51">Fujitsu-Siemens</option>
                <option value="43" data-href="/catalogo?manufacturer=43">HP</option>
                <option value="45" data-href="/catalogo?manufacturer=45">Lenovo</option>
            </select>
    <select name="home_categories" disabled="">
        <option value="">Category</option>
    </select>
    <button type="button" id="form-find-submit" data-href="" disabled="">Submeter</button>
</form>

        </div>
      </div>
    </div>
  </div>
</div>

The method I want to use is an Ajax Post to the controller, which will retrieve the data I need. I'm using this script to handle and request the data:

<script>
require(['jquery', 'jquery/ui'], function($){
    $("select[name=home_manufacturers]").change(function () {
        $("#form-find-submit").attr('disabled', 'disabled');
        $("select[name=home_categories]").attr('disabled', 'disabled');
        var manufacturer = this.value;
        var data_href = $('select[name=home_manufacturers] option:selected').data('href');

        $.ajax({
            showLoader: true,
            url: '',
            data: {
                manufacturer: manufacturer
            },
            type: "POST",
            dataType: 'json'
        }).done(function (data) { 
            var html = '';
            html += '<option value="">Por Categoria</option>';
            for (var key in data) {
                html += '<option value="' + key + '">' + data[key] + '</option>';
            }
            $("select[name=home_categories]").html(html);
            $("select[name=home_categories]").removeAttr('disabled');
            $("#form-find-submit").attr('data-href', data_href);
            $("#form-find-submit").removeAttr('disabled');

        });
    });

    $("select[name=home_categories]").change(function () {
        $("#form-find-submit").attr('disabled', 'disabled');
        var category = this.value;
        var manufacturer = $("select[name=home_manufacturers]").val();
        var manufacturer_name = $("select[name=home_manufacturers] option:selected").text();
        manufacturer_name = manufacturer_name.split('-').join('');
        manufacturer_name = manufacturer_name.split(' ').join('');
        manufacturer_name = manufacturer_name.split('_').join('');
        $.ajax({
            showLoader: true,
            url: '',
            data: {
                getUrl: 1,
                category: category,
                manufacturer: manufacturer
            },
            type: "POST",
            dataType: 'json'
        }).done(function (data) {
            $("#form-find-submit").attr('data-href', data + '/' + manufacturer_name.toLowerCase() + '.html');
            $("#form-find-submit").removeAttr('disabled');
        });
    });

    $("#form-find-submit").click(function () {
        window.location.href = $(this).data('href');
    });
});
</script>

Controller:

<?php
namespace Tiago\Pronet\Controller\Home;

use \Magento\Framework\App\Action\Action;
use \Magento\Framework\Controller\ResultFactory;
use \Magento\Framework\App\Action\Context;

class Display extends \Magento\Framework\App\Action\Action
{
    //protected $_pageFactory;
    private $layerResolver;
    protected $request;
    protected $collectionFactory; 
    protected $_categoryFactory;   
    protected $_categoryCollectionFactory;
    protected $_productRepository;
    protected $resultJsonFactory;

    public function __construct(
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory,
        \Magento\Catalog\Model\ProductFactory $productFactory,
        \Magento\Framework\App\Action\Context $context,
        \Magento\Catalog\Model\Layer\Resolver $layerResolver,
        \Magento\Framework\Controller\ResultFactory $resultJsonFactory,        
        \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory,
        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
        \Magento\Catalog\Model\ProductRepository $productRepository)
    {
        $this->collectionFactory = $collectionFactory;
        $this->layerResolver = $layerResolver;
        $this->_categoryCollectionFactory = $categoryCollectionFactory;
        $this->_productRepository = $productRepository;
        //$this->_pageFactory = $pageFactory;
        $this->resultJsonFactory = $resultJsonFactory;
        $this->_categoryFactory = $categoryFactory;
        $this->_productFactory = $productFactory;

        parent::__construct($context);
    }

    public function execute()
    {
        $response = array();
        //$brand = $this->getRequest()->getParam('manufacturer');
        $brand = $this->getRequest()->getPost('manufacturer');

        $resultJson = $this->resultJsonFactory->create(ResultFactory::TYPE_JSON);

        $productCollection = $this->getProductCollection($brand);
        $categoryCollection = $this->getCategoryCollection();
        foreach($productCollection as $product){
            $cats = $this->getProductCategoriesId($product->getData('entity_id')); //gets products cats id
            foreach($categoryCollection as $category){
                foreach($cats as $catstring){
                    if(strcmp($category->getData('entity_id'), $catstring) == 0){
                        $name = $this->getCategoryName($category->getData('entity_id'));
                        $response += array($category->getData('entity_id') => $name);
                    }
                }
            }
        }

        if($this->getRequest()->getPost('getUrl') == 1){
            $usedCategory = $this->getRequest()->getPost('category');
            $filtered_colection = $this->getFilteredCollection($usedCategory);
            $badCategories = $this->getBadCategories();
            $categories = $this->getCategories($filtered_colection, $badCategories);
            $categories = substr($categories, 0, -5);

            return $resultJson->setData($categories);
        }

        $response = array_unique($response);
        asort($response);
        //json_encode($response);

        return $resultJson->setData($response);
    }

    public function getBadCategories()
    {
        $bad_categories = "2";
        return explode(',', str_replace(' ', '', $bad_categories));
    }

    public function getFilteredCollection($categoryIds)
    {
        $collection = $this->_categoryCollectionFactory->create();
        $filtered_colection = $collection
            ->addFieldToSelect('*')
            ->addFieldToFilter(
                'entity_id',
                ['in' => $categoryIds]
            )
            ->setOrder('level', 'ASC')
            ->load();
        return $filtered_colection;
    }

    public function getCategories($filtered_colection, $badCategories)
    {
        $categories = '';
        foreach ($filtered_colection as $categoriesData) {
            if (!in_array($categoriesData->getId(), $badCategories)) {
                $categories .= $categoriesData->getUrl();
            }
        }
        return $categories;
    }

    public function getProductCategoriesId($pid)
    {
        $product = $this->_productFactory->create()->load($pid); // $pid = Product_ID
        $cats = $product->getCategoryIds();
        return $cats;
    }

    public function getCategoryName($categoryId)
    {
        $category = $this->_categoryFactory->create()->load($categoryId);
        $categoryName = $category->getName();
        return $categoryName;
    }

    public function getCategoryUrl()
    {
        $category = $this->_categoryFactory->create()->load($categoryId);
        $categoryName = $category->getName();
        return $categoryName;
    }

    public function getProductCollection($brand)
    {
    // Use factory to create a new product collection
        $productCollection = $this->collectionFactory->create();
    /** Apply filters here */
        $productCollection->addAttributeToSelect('*');
        $productCollection->addAttributeToFilter('manufacturer', $brand);

        return $productCollection; 
    } 


    public function getCategoryCollection($isActive = true, $level = false, $sortBy = false, $pageSize = false)
    {
        $collection = $this->_categoryCollectionFactory->create();
        $collection->addAttributeToSelect('*');        
        $collection->addAttributeToFilter('level',3);

        // select only active categories
        if ($isActive) {
            $collection->addIsActiveFilter();
        }

        // select categories of certain level

        //$collection->addLevelFilter(3);

        // sort categories by some value
        if ($sortBy) {
            $collection->addOrderField($sortBy);
        }

        // select certain number of categories
        if ($pageSize) {
            $collection->setPageSize($pageSize); 
        }    


        return $collection;
    }
}

Edit: Working solution

1 Answer 1

0

Your Action file Display.php location should be app\code\Tiago\Pronet\Controller\Home if your url is https://sonet.pt/pronet/home/display note controller folder Home should start with an uppercase letter as url is start with home not Home.

Also changes the namespace of Display.php to namespace Tiago\Pronet\Controller\Home; instead of \namespace Tiago\Pronet\Controller;

For Get request params use $this->getRequest()->getParams()

at Action files

POST $this->getRequest()->getPost()

2
  • Now I'm getting error 404, the ajax request is returning an html page.. Aug 29, 2019 at 8:42
  • It's working now, I've made the changes you suggested and voila! Now I just need to configure it to return exactly what I need. Thanks Amit Aug 30, 2019 at 10:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.