0

I, once again, have to ask for your help. I need to create a modal that let the customer select their car brand, model and year, and I need to populate the select options depending on the selections of the customer. Then, when the customer clicks on 'Save', I have to save the last category ID on a cookie, so I can use it later. I have made some tests but none of them has worked so far. Can you please help me?

My code:

app/code/Vendor/Module/view/frontend/templates/configCar.html

<div id="modal-content">
    <?php
    $parentCategory = $block->getMainCategory();
    ?>
    <div class="field llantas_marca required">
        <label class="label" for="llantas_marca"><span><?php echo __('Seleccione su marca') ?></span></label>
        <div class="control">
            <?php
            foreach ($parentCategory as $parent) {
                if ($parent->hasChildren()) {
                    $parentObj = $block->getCategoryById($parent->getId());
                    ?>
                    <select name="llantas_marca" id="llantas_marca" title="<?php echo __('Seleccione su marca') ?>" class="input-text"
                            data-validate="{required:true}">
                        <option value=""><?php echo __('Seleccione una marca') ?></option>
                        <?php
                        $childCategories = $parentObj->getChildrenCategories();
                        foreach ($childCategories as $child):
                            $childObj = $block->getCategoryById($child->getId());
                            ?>
                            <option value="<?php echo $child->getId() ?>"><?php echo $childObj->getName() ?></option>
                        <?php
                        endforeach;
                        ?>
                    </select>
                    <?php
                }
            }
            ?>
        </div>
    </div>
    <div class="field llantas_modelo required">
        <label class="label" for="llantas_modelo"><span><?php echo __('Seleccione un modelo') ?></span></label>
        <div class="control">
            <select name="llantas_modelo" id="llantas_modelo" title="<?php echo __('Seleccione un modelo') ?>" class="input-text"
                    data-validate="{required:true}">
                <option value=""><?php echo __('Seleccione un modelo') ?></option>
            </select>
        </div>
    </div>
    <div class="field llantas_ano required">
        <label class="label" for="llantas_ano"><span><?php echo __('Seleccione un año') ?></span></label>
        <div class="control">
            <select name="llantas_modelo" id="llantas_ano" title="<?php echo __('Seleccione un año') ?>" class="input-text"
                    data-validate="{required:true}">
                <option value=""><?php echo __('Seleccione un año') ?></option>
            </select>
        </div>
    </div>
</div>
<button id="configcar-modal-button" data-mage-init='{"configCar": {"target": "#modal-content"}}'>
    Configurador de Coche
</button>
<script>
    jQuery(document).on('change', '#llantas_marca', function () {
        var param = 'frame=' + jQuery('#llantas_marca').val();
        jQuery.ajax({
            showLoader: true,
            url: '<?php echo $block->getframeAction(); ?>',
            data: param,
            type: "GET",
            dataType: 'json'
        }).done(function (data) {
            jQuery('#llantas_modelo').empty();
            jQuery('#llantas_modelo').append(data.value);
        });
    });

    jQuery(document).on('change', '#llantas_modelo', function () {
        var param = 'frame=' + jQuery('#llantas_modelo').val();
        jQuery.ajax({
            showLoader: true,
            url: '<?php echo $block->getframeAction(); ?>',
            data: param,
            type: "GET",
            dataType: 'json'
        }).done(function (data) {
            jQuery('#llantas_ano').empty();
            jQuery('#llantas_ano').append(data.value);
        });
    });
</script>

app/code/Vendor/Module/Block/ConfigCar.php

<?php

namespace Vendor\Module\Block;

class ConfigCar extends \Magento\Framework\View\Element\Template
{
    protected $_isScopePrivate;
    protected $_categoryFactory;
    protected $_category;
    protected $_categoryHelper;
    protected $_categoryRepository;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
        \Magento\Catalog\Helper\Category $categoryHelper,
        \Magento\Catalog\Model\CategoryRepository $categoryRepository,
        array $data = []
    )
    {
        $this->_categoryFactory = $categoryFactory;
        $this->_categoryHelper = $categoryHelper;
        $this->_categoryRepository = $categoryRepository;
        parent::__construct($context, $data);
        $this->_isScopePrivate = true;
    }

    public function getframeAction()
    {
        $url = $this->getUrl('configcar/ajax-handler', ['_secure' => true]);
        return $url;
    }

    public function getMainCategory()
    {
        $this->_category = $this->_categoryFactory->create()
            ->getCollection()
            ->addAttributeToFilter('name', 'Por Vehículo')
            ->setPageSize(1);
        return $this->_category;
    }

    public function getCategoryById($categoryId)
    {
        return $this->_categoryRepository->get($categoryId);
    }
}

app/code/Vendor/Module/Controller/ajax-handler.php

<?php

namespace Vendor\Module\Controller;

class Frame extends \Magento\Framework\App\Action\Action
{
    protected $resultJsonFactory;

    protected $regionColFactory;

    public function __construct(
        \Magento\Framework\App\Action\Context            $context,
        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
        \Magento\Directory\Model\RegionFactory           $regionColFactory)
    {
        $this->regionColFactory = $regionColFactory;
        $this->resultJsonFactory = $resultJsonFactory;
        parent::__construct($context);
    }

    public function execute()
    {
        $result = $this->resultJsonFactory->create();

        $html = '<option selected="selected" value="">Seleccione una opción</option>';

        $frameName = $this->getRequest()->getParam('frame');
        if ($frameName != '') {
            switch ($frameName) {
                case '6858' :
                    $html .= '<option value="Option 1">Opción 1</option>';
                    $html .= '<option value="Option 2">Opción 2</option>';
                    break;

                default :
                    $html .= '<option value="Option 1">Opción 1</option>';
                    break;

            }
        }

        return $result->setData(['success' => true, 'value' => $html]);
    }
}

I think part of my problem resides in that I don't know what exact URL I have to pass to Ajax, and so the petition doesn't get done right. I apreciate all the help I could get

Thanks in advance!

1 Answer 1

0

I would go over the basics of creating a controller in Magento 2 first https://devdocs.magento.com/videos/fundamentals/create-a-new-page/.

A route in Magento 2 is composed by 3 components: frontName/controllerName/actionName.

The first part, the frontName, comes from your declaration in etc/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="configcar" frontName="configcar">
            <module name="Vendor_Module" />
        </route>
    </router>
</config>

Which in this case will be "configcar". (Don't forget to update module name="Vendor_Module").

Next, inside the Vendor/Module/Controller you have to create a new folder. The name of this folder will correspond to the controllerName part of the route.

Lastly, inside this folder, you create a PHP class, which corresponds to the actionName.

So, as an example, your controller could look like app/code/Vendor/Module/Controller/AjaxHandler/Index.php

And inside the controller class, you would have to update the namespace: Vendor\Module\Controller\AjaxHandler

For some reason, in your example, your actual class is named "Frame". Update that to be the same as the file name of the class, in this example: class Index extends \Magento\Framework\App\Action\Action

So, having all this in place, you should have now the /configcar/ajaxhandler/index path available on the front end.

Hint: If your actionName is "index", you can skip it, so /configcar/ajaxhandler/index is the same as /configcar/ajaxhandler. If your controllerName were also "index", you could have skipped that one as well. You can check that for example on the checkout page, you can go to it by either typing /checkout/index/index, /checkout/index or just simply /checkout.

P.S. After you figure this out, try to refactor your controller to use Composition over inheritance, and instead of extending \Magento\Framework\App\Action\Action, implement \Magento\Framework\App\Action\HttpGetActionInterface.

1
  • Now I understand perfectly how this works and all works as intended. Thank you so much for the answer! Feb 1 at 9:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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