JS Widget: dos Widgets personalizados extendieron el mismo Widget principal Magento 2

10

Condición previa

Tengo 2 widgets personalizados que extienden el mismo widget principal.

  • Widget principal: Magento_ConfigurableProduct/js/configurable
  • Primer widget personalizado: Vendor_AModule/js/configurable
  • Segundo widget personalizado: Vendor_BModule/js/configurable

Primer widget personalizado require-config.js:

var config = {
    map: {
        '*': {
            configurable: 'Vendor_AModule/js/configurable'
        }
    }
};

Primer widget personalizado JS:

define([
    'jquery',
    'mage/translate',
    'Magento_ConfigurableProduct/js/configurable'
], function ($) {
    $.widget('vendor.configurable_awidget', $.mage.configurable, {
        /**
         * {@inheritDoc}
         */
        _configureElement: function (element) {
            this._super(element);
            alert('Custom widget A is triggered!');
        }
    });

    return $.vendor.configurable_awidget;
});

Segundo widget personalizado require-config.js:

var config = {
    map: {
        '*': {
            configurable: 'Vendor_BModule/js/configurable'
        }
    }
};

Segundo widget personalizado JS:

define([
    'jquery',
    'mage/translate',
    'Magento_ConfigurableProduct/js/configurable'
], function ($) {
    $.widget('vendor.configurable_bwidget', $.mage.configurable, {
        /**
         * {@inheritDoc}
         */
        _configureElement: function (element) {
            this._super(element);
            alert('Custom widget B is triggered!');
        }
    });

    return $.vendor.configurable_bwidget;
});

pasos para reproducir

Abro una página de interfaz de producto configurable.

Resultado Esperado

Los veo a ambos Custom widget B is triggered!y Custom widget A is triggered!alerta.

Resultado actual

Solo veo Custom widget B is triggered!alerta.

Pregunta

¿Cómo debe ser el código para que la página de interfaz del producto configurable muestre alertas de ambos widgets?

Rendy Eko Prastiyo
fuente

Respuestas:

12

Magento 2 tiene una característica menos conocida llamada require-js mixinque es útil para extender un módulo js desde múltiples lugares.

Tu requirejs-config.jsdebería verse así:

var config = {
    'config': {
        'mixins': {
            'Magento_ConfigurableProduct/js/configurable': {
                'Vendor_AModule/js/configurable': true
            }
        }
    }
};

El archivo js sería entonces:

define([
    'jquery',
    'mage/translate'
], function ($) {

    return function (widget) {
        $.widget('vendor.configurable_awidget', widget, {
            /**
             * {@inheritDoc}
             */
            _configureElement: function (element) {
                this._super(element);
                alert('Custom widget A is triggered!');
            }
        });
        return $.vendor.configurable_awidget;
    };
});

Este js devuelve una función que toma el módulo de destino como argumento y devuelve la versión extendida. De esta manera, puede extender el widget en diferentes lugares sin anular indeseados.

Aaron Allen
fuente
¡Excelente! Información útil Gracias. Olvidémixin
Khoa TruongDinh
Solo puedo ver AWidgeten su código, ¿cómo solicitarlo BWidget?
Rendy Eko Prastiyo
1
BWidgetse implementaría igual que AWidget.
Aaron Allen
Gracias señor, he implementado su código y funciona como debería.
Rendy Eko Prastiyo
@AaronAllen, +1 Buena información.
Rakesh Jesadiya
2

Asegúrese de que el módulo personalizado se cargue después de otros

<sequence> etiqueta para garantizar que los archivos necesarios de otros componentes ya estén cargados cuando se cargue su componente

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="Vendor_BModule" setup_version="1.0.1">
        <sequence>
            <module name="Vendor_AModule"/>
        </sequence>
    </module>
</config>

Podemos comprobar en app/etc/config.php. Su módulo personalizado debe ser de "nivel inferior" que otros.

<?php
return array (
  'modules' => 
  array (
    ......
    'Magento_ConfigurableProduct' => 1,
    ......
    'Vendor_AModule' => 1,
    ......
    'Vendor_BModule' => 1,
    ......
  ),
);

Podemos eliminar el módulo personalizado de la setup_moduletabla. Y luego, ejecute el comando de actualización de configuración nuevamente para reordenar la secuencia del módulo.

Necesitamos asegurarnos de que el js personalizado sea de "nivel inferior" que otros en requirejs-config.js.

pub / static / _requirejs / frontend / Magento / luma / en_US / requirejs-config.js

(function(require){

    ......

    (function() {

        var config = {
            map: {
                '*': {
                    configurable: 'Magento_ConfigurableProduct/js/configurable'
                }
            }
        };
        require.config(config);
    })();

    ......



    (function() {
        var config = {
            map: {
                '*': {
                    configurable: 'Vendor_AModule/js/configurable'
                }
            }
        };
        require.config(config);
    })();

    .....

    (function() {
        var config = {
            map: {
                '*': {
                    configurable : 'Vendor_BModule/js/configurable'
                }
            }
        };
        require.config(config);
    })();

    ......

})(require);

Declarar el módulo B

Debido a que el widget A fue "anulado", el widget Magento predeterminado ya. Entonces, en el Módulo B, necesitamos cargar el widget A y "anularlo" .

app / code / Vendor / BModule / view / frontend / requirejs-config.js

var config = {
    map: {
        '*': {
            configurable : 'Vendor_BModule/js/configurable'
        }
    }
};

app / code / Vendor / BModule / view / frontend / web / js / configurable.js

define([
    'jquery',
    'mage/translate',
    'Vendor_AModule/js/configurable' // Module A widget
], function ($) {
    $.widget('vendor.configurable_bwidget', $.vendor.configurable_awidget, {
        /**
         * {@inheritDoc}
         */
        _configureElement: function (element) {
            this._super(element);
            alert('Custom widget B is triggered!');
        }
    });

    return $.vendor.configurable_bwidget;
});

Después de todo, necesitamos ejecutar nuevamente la implementación de contenido estático.

Podemos leer más aquí: https://learn.jquery.com/jquery-ui/widget-factory/extending-widgets/#using-_super-and-_superapply-to-access-parents

Khoa TruongDinh
fuente
1
Gracias por tu respuesta. Implementé este método hace algún día, y sí, funcionó. Pero luego, me encuentro en un problema en el que AModule debe ser independiente de BModule, de modo que cuando desactivo AModule, BModule aún debería funcionar, y viceversa. Aquí es donde desafortunadamente su respuesta no puede manejar este problema.
Rendy Eko Prastiyo