1

i have use custom option in xyz product and my product option is required in admin i want to when select in category page and add to cart directly without going to product page.

when i have remove required field in admin and it working correctly in category page

Below Working Code..

<?php
$object_manager = \Magento\Framework\App\ObjectManager::getInstance();
$custom_options = $object_manager->get('Magento\Catalog\Model\Product\Option')->getProductOptionCollection($_product);
if (is_array($custom_options) && count($custom_options) > 0) {
    echo '<input type="hidden" name="selected_configurable_option" value="">';
}
foreach ($custom_options as $option) {
    $values = $option->getValues();
    if (is_array($values) && count($values) > 0) { ?>
        <div class="form-group">
            <select name="options[<?php echo $option->getOptionId(); ?>]" class="required product-custom-option admin__control-select form-control" title="" data-selector="options[1]" aria-required="true">
                <?php foreach ($values as $index => $value) { ?>
                    <?php if ($index === 0) { ?>
                        <option value="" selected>-- Please Select --</option>
                    <?php } else { ?>
                        <option value="<?php echo $value->getOptionTypeId(); ?>" price="<?php echo $value->getPrice(); ?>"><?php echo $value->getTitle(); ?></option>
                    <?php } ?>
                <?php } ?>
            </select>
        </div>
    <?php } ?>
<?php } ?>

product option showing like

enter image description here

6
  • You want here that is product contain only required fields then when you click on add to cart from category page then currently Magento redirect us on product page. You want to prevent that ? Is that correct ? Commented Nov 21, 2019 at 16:59
  • yes correct now what happend if my dropdown is not required then same page add to cart working and if required it then going to product page but i want to if required and i want to same page add to cart working and option showing like screenshot Commented Nov 21, 2019 at 17:05
  • Can you please provide more detail here. I'll check this tomorrow and try to find some solution for you. :) Commented Nov 21, 2019 at 17:24
  • @KishanSavaliya which type details you want? i want to required custom option value add to cart same page not going to product page currently if not required then same page working fine Commented Nov 21, 2019 at 17:35
  • I'll check this after some time. I'm little busy with my projects. I'll check this and ping you if I need anything from your side then. Commented Nov 22, 2019 at 4:40

1 Answer 1

2

You need to override getAddToCartUrl() function of Magento\Catalog\Block\Product\AbstractProduct. So let's create one Plugin for it.

Create di.xml file here in your custom module

app/code/Vendor/Module/etc/frontend/di.xml

Content for this file is..

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Block\Product\AbstractProduct">
        <plugin name="sk_abstract_product_plugin" type="Vendor\Module\Plugin\Block\Product\AbstractProductPlugin" />
    </type>
    <type name="Magento\CatalogSearch\Block\SearchResult\ListProduct">
        <plugin name="sk_abstract_product_plugin" type="Vendor\Module\Plugin\Block\Product\AbstractProductPlugin" />
    </type>
</config>

Now we will create one Plugin file here

app/code/Vendor/Module/Plugin/Block/Product/AbstractProductPlugin.php

Content for this file is..

<?php

namespace Vendor\Module\Plugin\Block\Product;

class AbstractProductPlugin
{
    protected $request;

    public function __construct(
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Framework\App\RequestInterface $request
    ){
        $this->_cartHelper = $context->getCartHelper();
        $this->request = $request;
    }

    public function afterGetAddToCartUrl(\Magento\Catalog\Block\Product\AbstractProduct $subject, $result, $product, $additional = [])
    {
        $moduleName = $this->request->getModuleName();
        $controller = $this->request->getControllerName();
        $action     = $this->request->getActionName();

        if(($moduleName == 'catalog' && $action == 'view' && $controller == 'category') || ($moduleName == 'catalogsearch' && $action == 'index' && $controller == 'result')){
            if (!$product->getTypeInstance()->isPossibleBuyFromList($product)) {
                if (!isset($additional['_escape'])) {
                    $additional['_escape'] = true;
                }
                if (!isset($additional['_query'])) {
                    $additional['_query'] = [];
                }
                $additional['_query']['options'] = 'cart';
                return $this->_cartHelper->getAddUrl($product, $additional);
            }
            return $this->_cartHelper->getAddUrl($product, $additional);
        }
        return $result;
    }
}

Now we will add below function in list.phtml file in last.

<script type="text/javascript">  
(function  () {    
    require(["jquery"], function($) {
        $(document).ready(function($) {

            $('.tocart').click(function () {
                var currentForm = $(this).closest('form');
                var currentProductFormAction = currentForm.attr('action');
                var originalUrl = currentProductFormAction.split('?');
                var addToCartUrl = originalUrl[0];
                var selectedOptionName = currentForm.children('div.form-group').find('select').attr('name');
                var selectedOptionValue = currentForm.children('div.form-group').find('select').attr('value');
                var optionNameAndValueString = selectedOptionName+"="+selectedOptionValue;
                var finalUrlOfAction = addToCartUrl+"?"+optionNameAndValueString;
                currentForm.attr('action',finalUrlOfAction);
                if (currentForm.valid()) {
                    currentForm.submit();
                } else {
                    return false;
                }
            });
        }); 

    });
})();
</script>

This is my complete list.phtml file for your reference. I've changed few things in your code you can check that here.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
use Magento\Framework\App\Action\Action;

?>
<?php
// phpcs:disable Magento2.Templates.ThisInTemplate.FoundThis

/**
 * Product list template
 *
 * @var $block \Magento\Catalog\Block\Product\ListProduct
 */
?>
<?php
$_productCollection = $block->getLoadedProductCollection();
$_helper = $this->helper(Magento\Catalog\Helper\Output::class);
?>
<?php if (!$_productCollection->count()) :?>
    <div class="message info empty"><div><?= $block->escapeHtml(__('We can\'t find products matching the selection.')) ?></div></div>
<?php else :?>
    <?= $block->getToolbarHtml() ?>
    <?= $block->getAdditionalHtml() ?>
    <?php
    if ($block->getMode() == 'grid') {
        $viewMode = 'grid';
        $imageDisplayArea = 'category_page_grid';
        $showDescription = false;
        $templateType = \Magento\Catalog\Block\Product\ReviewRendererInterface::SHORT_VIEW;
    } else {
        $viewMode = 'list';
        $imageDisplayArea = 'category_page_list';
        $showDescription = true;
        $templateType = \Magento\Catalog\Block\Product\ReviewRendererInterface::FULL_VIEW;
    }
    /**
     * Position for actions regarding image size changing in vde if needed
     */
    $pos = $block->getPositioned();
    ?>
    <div class="products wrapper <?= /* @noEscape */ $viewMode ?> products-<?= /* @noEscape */ $viewMode ?>">
        <ol class="products list items product-items">
            <?php /** @var $_product \Magento\Catalog\Model\Product */ ?>
            <?php foreach ($_productCollection as $_product) :?>
            <li class="item product product-item">
                <div class="product-item-info" data-container="product-<?= /* @noEscape */ $viewMode ?>">
                    <?php
                    $productImage = $block->getImage($_product, $imageDisplayArea);
                    if ($pos != null) {
                        $position = ' style="left:' . $productImage->getWidth() . 'px;'
                            . 'top:' . $productImage->getHeight() . 'px;"';
                    }
                    ?>
                    <?php // Product Image ?>
                    <a href="<?= $block->escapeUrl($_product->getProductUrl()) ?>"
                       class="product photo product-item-photo"
                       tabindex="-1">
                        <?= $productImage->toHtml() ?>
                    </a>
                    <div class="product details product-item-details">
                        <?php
                            $_productNameStripped = $block->stripTags($_product->getName(), null, true);
                        ?>
                        <strong class="product name product-item-name">
                            <a class="product-item-link"
                               href="<?= $block->escapeUrl($_product->getProductUrl()) ?>">
                                <?= /* @noEscape */ $_helper->productAttribute($_product, $_product->getName(), 'name') ?>
                            </a>
                        </strong>
                        <?= $block->getReviewsSummaryHtml($_product, $templateType) ?>
                        <?= /* @noEscape */ $block->getProductPrice($_product) ?>
                        <?= $block->getProductDetailsHtml($_product) ?>

                        <div class="product-item-inner">
                            <div class="product actions product-item-actions"<?= strpos($pos, $viewMode . '-actions') ? $block->escapeHtmlAttr($position) : '' ?>>
                                <div class="actions-primary"<?= strpos($pos, $viewMode . '-primary') ? $block->escapeHtmlAttr($position) : '' ?>>
                                    <?php if ($_product->isSaleable()) :?>
                                        <?php $postParams = $block->getAddToCartPostParams($_product); ?>
                                        <form data-role="tocart-form"
                                              data-product-sku="<?= $block->escapeHtml($_product->getSku()) ?>"
                                              action="<?= $block->escapeUrl($postParams['action']) ?>"
                                              method="post">
                                            <input type="hidden"
                                                   name="product"
                                                   value="<?= /* @noEscape */ $postParams['data']['product'] ?>">
                                            <input type="hidden" name="<?= /* @noEscape */ Action::PARAM_NAME_URL_ENCODED ?>"
                                                   value="<?= /* @noEscape */ $postParams['data'][Action::PARAM_NAME_URL_ENCODED] ?>">
                                            <?= $block->getBlockHtml('formkey') ?>
                                            <?php
                                                $object_manager = \Magento\Framework\App\ObjectManager::getInstance();
                                                $custom_options = $object_manager->get('Magento\Catalog\Model\Product\Option')->getProductOptionCollection($_product);
                                                if (is_array($custom_options) && count($custom_options) > 0) {
                                                    echo '<input type="hidden" name="selected_configurable_option" value="">';
                                                }
                                                foreach ($custom_options as $option) {
                                                    $values = $option->getValues();
                                                    if (is_array($values) && count($values) > 0) { ?>
                                                        <div class="form-group">
                                                            <select name="options[<?php echo $option->getOptionId(); ?>]" class="required product-custom-option admin__control-select form-control" title="" data-selector="options[1]" aria-required="true">
                                                                <?php foreach ($values as $index => $value) { ?>
                                                                    <?php if ($index === 0) { ?>
                                                                        <option value="" selected>-- Please Select --</option>
                                                                    <?php } else { ?>
                                                                        <option value="<?php echo $value->getOptionTypeId(); ?>" price="<?php echo $value->getPrice(); ?>"><?php echo $value->getTitle(); ?></option>
                                                                    <?php } ?>
                                                                <?php } ?>
                                                            </select>
                                                        </div>
                                                    <?php } ?>
                                                <?php } ?>
                                            <button type="submit"
                                                    title="<?= $block->escapeHtmlAttr(__('Add to Cart')) ?>"
                                                    class="action tocart primary">
                                                <span><?= $block->escapeHtml(__('Add to Cart')) ?></span>
                                            </button>
                                        </form>
                                    <?php else :?>
                                        <?php if ($_product->isAvailable()) :?>
                                            <div class="stock available"><span><?= $block->escapeHtml(__('In stock')) ?></span></div>
                                        <?php else :?>
                                            <div class="stock unavailable"><span><?= $block->escapeHtml(__('Out of stock')) ?></span></div>
                                        <?php endif; ?>
                                    <?php endif; ?>
                                </div>
                                <div data-role="add-to-links" class="actions-secondary"<?= strpos($pos, $viewMode . '-secondary') ? $block->escapeHtmlAttr($position) : '' ?>>
                                    <?php if ($addToBlock = $block->getChildBlock('addto')) :?>
                                        <?= $addToBlock->setProduct($_product)->getChildHtml() ?>
                                    <?php endif; ?>
                                </div>
                            </div>
                            <?php if ($showDescription) :?>
                                <div class="product description product-item-description">
                                    <?= /* @noEscape */ $_helper->productAttribute($_product, $_product->getShortDescription(), 'short_description') ?>
                                    <a href="<?= $block->escapeUrl($_product->getProductUrl()) ?>"
                                       title="<?= /* @noEscape */ $_productNameStripped ?>"
                                       class="action more"><?= $block->escapeHtml(__('Learn More')) ?></a>
                                </div>
                            <?php endif; ?>
                        </div>
                    </div>
                </div>
            </li>
            <?php endforeach; ?>
        </ol>
    </div>
    <?= $block->getToolbarHtml() ?>
    <?php if (!$block->isRedirectToCartEnabled()) :?>
        <script type="text/x-magento-init">
        {
            "[data-role=tocart-form], .form.map.checkout": {
                "catalogAddToCart": {
                    "product_sku": "<?= $block->escapeJs($_product->getSku()) ?>"
                }
            }
        }
        </script>
    <?php endif; ?>
<?php endif; ?>

<script type="text/javascript">  
(function  () {    
    require(["jquery"], function($) {
        $(document).ready(function($) {

            $('.tocart').click(function () {
                var currentForm = $(this).closest('form');
                var currentProductFormAction = currentForm.attr('action');
                var originalUrl = currentProductFormAction.split('?');
                var addToCartUrl = originalUrl[0];
                var selectedOptionName = currentForm.children('div.form-group').find('select').attr('name');
                var selectedOptionValue = currentForm.children('div.form-group').find('select').attr('value');
                var optionNameAndValueString = selectedOptionName+"="+selectedOptionValue;
                var finalUrlOfAction = addToCartUrl+"?"+optionNameAndValueString;
                currentForm.attr('action',finalUrlOfAction);
                if (currentForm.valid()) {
                    currentForm.submit();
                } else {
                    return false;
                }
            });
        }); 

    });
})();
</script>

You can make changes based on your requirement in phtml file. I've checked this with Default Magento 2.3.3 and that is working for me.

Hope this will help you!

Your Answer

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

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