Magento 2 In den Warenkorb Frontend Event Listener

10

Ich versuche eine gute Lösung zu finden, um benutzerdefiniertes Javascript auszuführen, wenn das Produkt erfolgreich in den Warenkorb gelegt wurde. Auch diese kundenspezifische Javascript Notwendigkeit , Informationen über Produkt , das dem Warenkorb aufgenommen ( sku, qty, price, name, etc.)

Derzeit habe ich folgende Möglichkeiten, um Informationen zu Produkten zu erhalten, die dem Warenkorb hinzugefügt wurden:

  1. Umschreiben $.mage.catalogAddToCart.prototype.enableAddToCartButton(für Produkte, die aus dem Katalog oder der Produktansicht in den Warenkorb gelegt wurden)
  2. Umschreiben $.mage.dataPost.prototype.postData(für Produkte, die über Widgets in den Warenkorb gelegt wurden)

Um die notwendigen Informationen zu erhalten, muss ich die Seite analysieren (z. qtyB. um skusie zu erhalten ) und zusätzliche Informationen auf die Seite ausgeben (z. B. um sie zu erhalten product id).

Jedoch meine Lösung:

  • hat zwei Einstiegspunkte
  • sieht nicht gut aus
  • Behandelt keine Situation, in der die Validierung im Backend fehlgeschlagen ist
  • bietet mir nicht alle erforderlichen Informationen bequem an

Leider konnte ich keinen geeigneten Erweiterungspunkt für den Checkout-Minicart finden, um mein Problem zu lösen.

Anregungen sind sehr willkommen!

Sergii Ivashchenko
quelle
Ich habe eine ähnliche Situation. Ich habe Magento-Code und -Logik überprüft und finde keine Lösung. Magento unterstützt es also nicht und möglicherweise ist es sinnvoll, weil Sie Produkte ohne Ajax-Anfrage hinzufügen können. Aber ich muss eine Lösung für meine Aufgabe haben und habe die folgende Datei (cart-update.js) geschrieben: require (['jquery', 'underscore', 'jquery / jquery-storageapi'], function ($, _) { var storage = $ .initNamespaceStorage ('mage-cache-storage'). localStorage; $ (document) .on ('ajaxComplete', Funktion (Ereignis, xhr, Einstellungen) {if (settings.url.match (/ customer \ / Abschnitt \ / load / i) && xhr.responseJSON && xhr.responseJ
Oleksiy
Haben Sie versucht, Mixins zu verwenden? alanstorm.com/the-curious-case-of-magento-2-mixins Ich persönlich benutze sie oft. Genau wie die PHP-Version von Plugins. Wenn Sie nicht weiterkommen, lassen Sie es mich wissen und ich kann Ihnen eine Lösung anbieten.
Chris Anderson
@ ChrisAnderson danke, aber tatsächlich wird meine derzeit in der Frage beschriebene hässliche Lösung mithilfe von Mixins implementiert.
Sergii Ivashchenko

Antworten:

1

Eine Lösung besteht darin, ein Mixin für die Funktion catalogAddToCart ajaxSubmit zu schreiben. Normalerweise sind die von Ihnen benötigten Daten hier nicht verfügbar. Dies kann jedoch durch Ändern des Checkout / Cart / Add-Controllers behoben werden, um die Daten zurückzugeben. Vollständige Lösung unten, derzeit werden nur die Daten angezeigt, die Sie für den Erfolg des Warenkorbs benötigen.

app / code / VendorName / ModuleName / registration.php

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

app / code / VendorName / ModuleName / 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="VendorName_ModuleName" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Catalog"/>
            <module name="Magento_Checkout"/>
        </sequence>
    </module>
</config>

app / code / VendorName / ModuleName / etc / frontend / di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Checkout\Controller\Cart\Add" type="VendorName\ModuleName\Controller\Cart\Add"/>
</config>

app / code / VendorName / ModuleName / Controller / Cart / Add.php

<?php

namespace VendorName\ModuleName\Controller\Cart;

/**
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Add extends \Magento\Checkout\Controller\Cart\Add
{
    /**
     * Add product to shopping cart action
     *
     * @return \Magento\Framework\Controller\Result\Redirect
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     */
    public function execute()
    {
        if (!$this->_formKeyValidator->validate($this->getRequest())) {
            return $this->resultRedirectFactory->create()->setPath('*/*/');
        }

        $params = $this->getRequest()->getParams();

        try {
            if (isset($params['qty'])) {
                $filter = new \Zend_Filter_LocalizedToNormalized(
                    ['locale' => $this->_objectManager->get(
                        \Magento\Framework\Locale\ResolverInterface::class
                    )->getLocale()]
                );
                $params['qty'] = $filter->filter($params['qty']);
            }

            $product = $this->_initProduct();
            $related = $this->getRequest()->getParam('related_product');

            /**
             * Check product availability
             */
            if (!$product) {
                return $this->goBack();
            }

            $this->cart->addProduct($product, $params);
            if (!empty($related)) {
                $this->cart->addProductsByIds(explode(',', $related));
            }

            $this->cart->save();

            /**
             * @todo remove wishlist observer \Magento\Wishlist\Observer\AddToCart
             */
            $this->_eventManager->dispatch(
                'checkout_cart_add_product_complete',
                ['product' => $product, 'request' => $this->getRequest(), 'response' => $this->getResponse()]
            );

            if (!$this->_checkoutSession->getNoCartRedirect(true)) {
                if (!$this->cart->getQuote()->getHasError()) {
                    $message = __(
                        'You added %1 to your shopping cart.',
                        $product->getName()
                    );
                    $this->messageManager->addSuccessMessage($message);
                }
                return $this->goBack(null, $product, [
                    'sku' => $product->getSku(),
                    'name' => $product->getName(),
                    'price' => $product->getPrice(),
                    'qty' => isset($params['qty'])?$params['qty']:null
                ]);
            }
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            if ($this->_checkoutSession->getUseNotice(true)) {
                $this->messageManager->addNotice(
                    $this->_objectManager->get(\Magento\Framework\Escaper::class)->escapeHtml($e->getMessage())
                );
            } else {
                $messages = array_unique(explode("\n", $e->getMessage()));
                foreach ($messages as $message) {
                    $this->messageManager->addError(
                        $this->_objectManager->get(\Magento\Framework\Escaper::class)->escapeHtml($message)
                    );
                }
            }

            $url = $this->_checkoutSession->getRedirectUrl(true);

            if (!$url) {
                $cartUrl = $this->_objectManager->get(\Magento\Checkout\Helper\Cart::class)->getCartUrl();
                $url = $this->_redirect->getRedirectUrl($cartUrl);
            }

            return $this->goBack($url);
        } catch (\Exception $e) {
            $this->messageManager->addException($e, __('We can\'t add this item to your shopping cart right now.'));
            $this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
            return $this->goBack();
        }
    }

    /**
     * Resolve response
     *
     * @param string $backUrl
     * @param \Magento\Catalog\Model\Product $product
     * @return $this|\Magento\Framework\Controller\Result\Redirect
     */
    protected function goBack($backUrl = null, $product = null, $result = [])
    {
        if (!$this->getRequest()->isAjax()) {
            return parent::_goBack($backUrl);
        }

        if ($backUrl || $backUrl = $this->getBackUrl()) {
            $result['backUrl'] = $backUrl;
        } else {
            if ($product && !$product->getIsSalable()) {
                $result['product'] = [
                    'statusText' => __('Out of stock')
                ];
            }
        }

        $this->getResponse()->representJson(
            $this->_objectManager->get(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($result)
        );
    }
}

app / code / VendorName / ModuleName / view / frontend / requirejs-config.js

var config = {
    config: {
        mixins: {
            'Magento_Catalog/js/catalog-add-to-cart': {
                'VendorName_ModuleName/js/catalog-add-to-cart-mixin': true
            },
        }
    }
};

app / code / VendorName / ModuleName / view / frontend / web / js / catalog-add-to-cart-mixin.js

define([
    'jquery',
], function ($) {
    'use strict';

    return function (widget) {
        $.widget('mage.catalogAddToCart', widget, {
            /**
             * @param {String} form
             */
            ajaxSubmit: function (form) {
                var self = this;

                $(self.options.minicartSelector).trigger('contentLoading');
                self.disableAddToCartButton(form);

                $.ajax({
                    url: form.attr('action'),
                    data: form.serialize(),
                    type: 'post',
                    dataType: 'json',

                    /** @inheritdoc */
                    beforeSend: function () {
                        if (self.isLoaderEnabled()) {
                            $('body').trigger(self.options.processStart);
                        }
                    },

                    /** @inheritdoc */
                    success: function (res) {
                        alert(JSON.stringify(res));
                        var eventData, parameters;

                        $(document).trigger('ajax:addToCart', form.data().productSku);

                        if (self.isLoaderEnabled()) {
                            $('body').trigger(self.options.processStop);
                        }

                        if (res.backUrl) {
                            eventData = {
                                'form': form,
                                'redirectParameters': []
                            };
                            // trigger global event, so other modules will be able add parameters to redirect url
                            $('body').trigger('catalogCategoryAddToCartRedirect', eventData);

                            if (eventData.redirectParameters.length > 0) {
                                parameters = res.backUrl.split('#');
                                parameters.push(eventData.redirectParameters.join('&'));
                                res.backUrl = parameters.join('#');
                            }
                            window.location = res.backUrl;

                            return;
                        }

                        if (res.messages) {
                            $(self.options.messagesSelector).html(res.messages);
                        }

                        if (res.minicart) {
                            $(self.options.minicartSelector).replaceWith(res.minicart);
                            $(self.options.minicartSelector).trigger('contentUpdated');
                        }

                        if (res.product && res.product.statusText) {
                            $(self.options.productStatusSelector)
                                .removeClass('available')
                                .addClass('unavailable')
                                .find('span')
                                .html(res.product.statusText);
                        }
                        self.enableAddToCartButton(form);
                    }
                });
            }
        });

        return $.mage.catalogAddToCart;
    }
});
Media Lounge
quelle
1

Wenn etwas zum Warenkorb hinzugefügt wird, werden die lokalen Speicherinformationen aktualisiert und Sie können einen Knockout abonnieren, der im cartAbschnitt der Kundendaten zu beobachten ist, um benachrichtigt zu werden, wenn sich der Inhalt ändert.

Hier ist ein Beispiel:

require(['Magento_Customer/js/customer-data'], function (customerData) {

    var cart = customerData.get('cart');
    var count = cart().summary_count;
    cart.subscribe(function () {
        if (cart().summary_count !== count) {
            count = cart().summary_count;
            // do something here
            console.log('Number of items in cart is now: ' + count);
        }
    });
});
Quinten
quelle
Auch mit einem "domReady!" scheint im require-Block zu früh als cart () zu laufen. summary_count immer 'undefined'?
00-BBB
Deshalb abonnieren Sie den Warenkorb
Quinten