Comprensión del tema Magento: personalizaciones de diseño

Hola amigos !!

En este blog, discutiremos sobre los puntos relacionados con las personalizaciones del diseño del tema de Magento.

Entonces, en primer lugar, intentamos comprender cómo podemos crear un tema personalizado en Magento 2. Puede consultar nuestro blog Tema personalizado en Magento 2 para crear un tema personalizado.

Al crear un tema personalizado, siempre debemos utilizar las mejores prácticas para el desarrollo de temas para evitar conflictos y problemas con nuestro tema después de actualizar nuestra instancia de Magento.

Puede consultar nuestro blog Mejor enfoque para crear un tema en Magento 2 para evitar problemas de conflicto.

Ahora, volviendo a nuestro tema, para personalizaciones de diseño en el tema Magento, cubriremos los siguientes temas: –

1. Anular el diseño de Core Magento

En el siguiente ejemplo, anulamos el diseño del módulo Magento_Catalog/catalog_category_view.xml a nuestro tema personalizado para eliminar el pan de la página de vista de categorías.

Para lograr esto, creamos un mismo archivo de diseño (catalog_category_view.xml) dentro del siguiente directorio de temas: –

aplicación/diseño/frontend/Webkul/customtheme/Magento_Catalog/layout/

<?xml version="1.0"?>
<!--
/**
 * Webkul Software.
 *
 * @category   Webkul
 * @package    Webkul_CustomTheme
 * @author     Webkul Software Private Limited
 * @copyright  Webkul Software Private Limited (https://webkul.com)
 * @license    https://store.webkul.com/license.html
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="breadcrumbs" remove="true"/>
    </body>
</page>

Aquí está el resultado del código mencionado. Breadcumbs se ha eliminado de la página de vista de categorías.

2. Anular el estilo principal de Magento

En el siguiente ejemplo, anulamos el archivo de estilo web/css/_module.less del módulo Magento_Catalog a nuestro tema personalizado para cambiar el color del botón Agregar al carrito.

Para lograr esto, creamos un mismo archivo de estilo (_module.less) dentro del siguiente directorio de temas: –

aplicación/diseño/frontend/Webkul/customtheme/Magento_Catalog/Web/css/

@import 'source/_extend.less';
.actions-primary{
    background-color: red;
    border:1px solid red;
    color:#fff;
}

Aquí está el resultado del código mencionado.

Imagen 1: – Sin anular el CSS.

Personalizaciones-de-diseños-de-tema-antes-de-anulación-css

Imagen 2: – Con anulación de CSS. Se ha cambiado el color del botón Agregar al carrito.

Personalizaciones-de-diseños-de-tema-después-de-anulación-css

3. Anular la plantilla principal de Magento

En el siguiente ejemplo, anulamos el archivo de plantilla templates/product/list.phtml del módulo Magento_Catalog a nuestro tema personalizado para reemplazar el texto Agregar al carrito con Comprar ahora.

Para lograr esto, creamos un mismo archivo de plantilla (list.phtml) dentro del siguiente directorio: –

aplicación/diseño/frontend/Webkul/customtheme/Magento_Catalog/templates/product/

<?php
/**
 * Webkul Software.
 *
 * @category   Webkul
 * @package    Webkul_CustomTheme
 * @author     Webkul Software Private Limited
 * @copyright  Webkul Software Private Limited (https://webkul.com)
 * @license    https://store.webkul.com/license.html
 */
use Magento\Framework\App\Action\Action;

/**
 * Product list template
 *
 * @var $block \Magento\Catalog\Block\Product\ListProduct
 * @var \Magento\Framework\Escaper $escaper
 * @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer
 */
?>
<?php
$_productCollection = $block->getLoadedProductCollection();
/** @var \Magento\Catalog\Helper\Output $_helper */
$_helper = $block->getData('outputHelper');
?>
<?php if (!$_productCollection->count()): ?>
    <div class="message info empty">
        <div><?= $escaper->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"
                     id="product-item-info_<?= /* @noEscape */ $_product->getId() ?>"
                     data-container="product-<?= /* @noEscape */ $viewMode ?>">
                    <?php
                    $productImage = $block->getImage($_product, $imageDisplayArea);
                    if ($pos != null) {
                        $position = 'left:' . $productImage->getWidth() . 'px;'
                            . 'top:' . $productImage->getHeight() . 'px;';
                    }
                    ?>
                    <?php // Product Image ?>
                    <a href="<?= $escaper->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="<?= $escaper->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">
                                <div class="actions-primary">
                                    <?php if ($_product->isSaleable()):?>
                                        <?php $postParams = $block->getAddToCartPostParams($_product); ?>
                                        <form data-role="tocart-form"
                                              data-product-sku="<?= $escaper->escapeHtml($_product->getSku()) ?>"
                                              action="<?= $escaper->escapeUrl($postParams['action']) ?>"
                                              data-mage-init='{"catalogAddToCart": {}}'
                                              method="post">
                                            <?php $options = $block->getData('viewModel')->getOptionsData($_product); ?>
                                            <?php foreach ($options as $optionItem): ?>
                                                <input type="hidden"
                                                       name="<?= $escaper->escapeHtml($optionItem['name']) ?>"
                                                       value="<?= $escaper->escapeHtml($optionItem['value']) ?>">
                                            <?php endforeach; ?>
                                            <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') ?>
                                            <button type="submit"
                                                    title="<?= $escaper->escapeHtmlAttr(__('Purchase Now')) ?>"
                                                    class="action tocart primary"
                                                    disabled>
                                                <span><?= $escaper->escapeHtml(__('Purchase Now')) ?></span>
                                            </button>
                                        </form>
                                    <?php else:?>
                                        <?php if ($_product->isAvailable()):?>
                                            <div class="stock available">
                                                <span><?= $escaper->escapeHtml(__('In stock')) ?></span></div>
                                        <?php else:?>
                                            <div class="stock unavailable">
                                                <span><?= $escaper->escapeHtml(__('Out of stock')) ?></span></div>
                                        <?php endif; ?>
                                    <?php endif; ?>
                                </div>
                                <?= ($pos && strpos($pos, $viewMode . '-primary')) ?
                                    /* @noEscape */ $secureRenderer->renderStyleAsTag(
                                        $position,
                                        'product-item-info_' . $_product->getId() . ' div.actions-primary'
                                    ) : '' ?>
                                <div data-role="add-to-links" class="actions-secondary">
                                    <?php if ($addToBlock = $block->getChildBlock('addto')): ?>
                                        <?= $addToBlock->setProduct($_product)->getChildHtml() ?>
                                    <?php endif; ?>
                                </div>
                                <?= ($pos && strpos($pos, $viewMode . '-secondary')) ?
                                    /* @noEscape */ $secureRenderer->renderStyleAsTag(
                                        $position,
                                        'product-item-info_' . $_product->getId() . ' div.actions-secondary'
                                    ) : '' ?>
                            </div>
                            <?php if ($showDescription): ?>
                                <div class="product description product-item-description">
                                    <?= /* @noEscape */ $_helper->productAttribute(
                                        $_product,
                                        $_product->getShortDescription(),
                                        'short_description'
                                    ) ?>
                                    <a href="<?= $escaper->escapeUrl($_product->getProductUrl()) ?>"
                                       title="<?= /* @noEscape */ $_productNameStripped ?>"
                                       class="action more"><?= $escaper->escapeHtml(__('Learn More')) ?></a>
                                </div>
                            <?php endif; ?>
                        </div>
                    </div>
                </div>
                <?= ($pos && strpos($pos, $viewMode . '-actions')) ?
                /* @noEscape */ $secureRenderer->renderStyleAsTag(
                    $position,
                    'product-item-info_' . $_product->getId() . ' div.product-item-actions'
                ) : '' ?>
            </li>
            <?php endforeach; ?>
        </ol>
    </div>
    <?= $block->getChildBlock('toolbar')->setIsBottom(true)->toHtml() ?>
    <?php // phpcs:ignore Magento2.Legacy.PhtmlTemplate ?>
<?php endif; ?>

Aquí está el resultado del código mencionado. El texto Agregar al carrito ha sido reemplazado por Comprar ahora.

Personalizaciones-de-diseños-de-tema-anulación-de-plantilla-1

4. Anular Core Magento js

En el siguiente ejemplo, anulamos el archivo web/js/view/paid/default.js del módulo Magento_Checkout a nuestro tema personalizado para agregar confirmación para realizar el botón de pedido al hacer clic en la acción.

Para lograr esto, creamos un mismo archivo js (default.js) dentro del siguiente directorio: –

aplicación/diseño/frontend/Webkul/customtheme/Magento_Checkout/web/js/view/pago/

/**
 * Webkul Software.
 *
 * @category   Webkul
 * @package    Webkul_CustomTheme
 * @author     Webkul Software Private Limited
 * @copyright  Webkul Software Private Limited (https://webkul.com)
 * @license    https://store.webkul.com/license.html
 */

 define([
    'ko',
    'jquery',
    'uiComponent',
    'Magento_Checkout/js/action/place-order',
    'Magento_Checkout/js/action/select-payment-method',
    'Magento_Checkout/js/model/quote',
    'Magento_Customer/js/model/customer',
    'Magento_Checkout/js/model/payment-service',
    'Magento_Checkout/js/checkout-data',
    'Magento_Checkout/js/model/checkout-data-resolver',
    'uiRegistry',
    'Magento_Checkout/js/model/payment/additional-validators',
    'Magento_Ui/js/model/messages',
    'uiLayout',
    'Magento_Checkout/js/action/redirect-on-success',
    'Magento_Ui/js/modal/confirm'
], function (
    ko,
    $,
    Component,
    placeOrderAction,
    selectPaymentMethodAction,
    quote,
    customer,
    paymentService,
    checkoutData,
    checkoutDataResolver,
    registry,
    additionalValidators,
    Messages,
    layout,
    redirectOnSuccessAction,
    confirmation
) {
    'use strict';

    return Component.extend({
        redirectAfterPlaceOrder: true,
        isPlaceOrderActionAllowed: ko.observable(quote.billingAddress() != null),

        /**
         * After place order callback
         */
        afterPlaceOrder: function () {
            // Override this function and put after place order logic here
        },

        /**
         * Initialize view.
         *
         * @return {exports}
         */
        initialize: function () {
            var billingAddressCode,
                billingAddressData,
                defaultAddressData;

            this._super().initChildren();
            quote.billingAddress.subscribe(function (address) {
                this.isPlaceOrderActionAllowed(address !== null);
            }, this);
            checkoutDataResolver.resolveBillingAddress();

            billingAddressCode = 'billingAddress' + this.getCode();
            registry.async('checkoutProvider')(function (checkoutProvider) {
                defaultAddressData = checkoutProvider.get(billingAddressCode);

                if (defaultAddressData === undefined) {
                    // Skip if payment does not have a billing address form
                    return;
                }
                billingAddressData = checkoutData.getBillingAddressFromData();

                if (billingAddressData) {
                    checkoutProvider.set(
                        billingAddressCode,
                        $.extend(true, {}, defaultAddressData, billingAddressData)
                    );
                }
                checkoutProvider.on(billingAddressCode, function (providerBillingAddressData) {
                    checkoutData.setBillingAddressFromData(providerBillingAddressData);
                }, billingAddressCode);
            });

            return this;
        },

        /**
         * Initialize child elements
         *
         * @returns {Component} Chainable.
         */
        initChildren: function () {
            this.messageContainer = new Messages();
            this.createMessagesComponent();

            return this;
        },

        /**
         * Create child message renderer component
         *
         * @returns {Component} Chainable.
         */
        createMessagesComponent: function () {

            var messagesComponent = {
                parent: this.name,
                name: this.name + '.messages',
                displayArea: 'messages',
                component: 'Magento_Ui/js/view/messages',
                config: {
                    messageContainer: this.messageContainer
                }
            };

            layout([messagesComponent]);

            return this;
        },

        /**
         * Place order.
         */
        placeOrder: function (data, event) {
            var self = this;
            confirmation({
                title: 'Order Confirmation',
                content: 'Do you want to place this order?',
                actions: {
                    confirm: function () {
                        if (event) {
                            event.preventDefault();
                        }
            
                        if (self.validate() &&
                            additionalValidators.validate() &&
                            self.isPlaceOrderActionAllowed() === true
                        ) {
                            self.isPlaceOrderActionAllowed(false);
            
                            self.getPlaceOrderDeferredObject()
                                .done(
                                    function () {
                                        self.afterPlaceOrder();
            
                                        if (self.redirectAfterPlaceOrder) {
                                            redirectOnSuccessAction.execute();
                                        }
                                    }
                                ).always(
                                    function () {
                                        self.isPlaceOrderActionAllowed(true);
                                    }
                                );
            
                            return true;
                        }
                    },
                    cancel: function () {
                        return false;
                    }
                }
            });
            return false;
        },

        /**
         * @return {*}
         */
        getPlaceOrderDeferredObject: function () {
            return $.when(
                placeOrderAction(this.getData(), this.messageContainer)
            );
        },

        /**
         * @return {Boolean}
         */
        selectPaymentMethod: function () {
            selectPaymentMethodAction(this.getData());
            checkoutData.setSelectedPaymentMethod(this.item.method);

            return true;
        },

        isChecked: ko.computed(function () {
            return quote.paymentMethod() ? quote.paymentMethod().method : null;
        }),

        isRadioButtonVisible: ko.computed(function () {
            return paymentService.getAvailablePaymentMethods().length !== 1;
        }),

        /**
         * Get payment method data
         */
        getData: function () {
            return {
                'method': this.item.method,
                'po_number': null,
                'additional_data': null
            };
        },

        /**
         * Get payment method type.
         */
        getTitle: function () {
            return this.item.title;
        },

        /**
         * Get payment method code.
         */
        getCode: function () {
            return this.item.method;
        },

        /**
         * @return {Boolean}
         */
        validate: function () {
            return true;
        },

        /**
         * @return {String}
         */
        getBillingAddressFormName: function () {
            return 'billing-address-form-' + this.item.method;
        },

        /**
         * Dispose billing address subscriptions
         */
        disposeSubscriptions: function () {
            // dispose all active subscriptions
            var billingAddressCode = 'billingAddress' + this.getCode();

            registry.async('checkoutProvider')(function (checkoutProvider) {
                checkoutProvider.off(billingAddressCode);
            });
        }
    });
});

Aquí está el resultado del código mencionado. La confirmación se ha agregado al hacer clic en el botón Realizar pedido.

Diseños de tema-personalizaciones-anulación-js

Eso es todo sobre el tema Magento: personalizaciones de diseño. Esperamos que esto sea útil.

Si tiene alguna pregunta, comente a continuación e intentaremos responderle.

¡Gracias! 🙂


Source link

About David Lopez

Check Also

Cómo optimizar las operaciones de fabricación mediante soluciones de automatización de procesos

Sinopsis: ¿Cómo conciliar estas dos realidades globales contrastantes? Por un lado, gracias a la automatización …

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *