JS Widget: dois Widgets personalizados estenderam o mesmo pai Widget Magento 2

10

Condição prévia

Eu tenho 2 widgets personalizados que estendem o mesmo widget pai.

  • Widget pai: Magento_ConfigurableProduct/js/configurable
  • Primeiro widget personalizado: Vendor_AModule/js/configurable
  • Segundo widget personalizado: Vendor_BModule/js/configurable

Primeiro widget personalizado require-config.js:

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

Primeiro JS de widget personalizado:

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 JS de widget personalizado:

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;
});

Passos para reproduzir

Abro uma página de front-end de produto configurável.

resultado esperado

Eu vejo os dois Custom widget B is triggered!e Custom widget A is triggered!alerta.

Resultado atual

Eu só vejo Custom widget B is triggered!alerta.

Questão

Como deve ser o código para que a página de front-end do produto configurável exiba alertas dos dois widgets?

Rendy Eko Prastiyo
fonte

Respostas:

12

O Magento 2 possui um recurso menos conhecido, chamado de require-js mixin, útil para estender um módulo js de vários locais.

Você requirejs-config.jsdeve se parecer com:

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

O arquivo js seria então:

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 retorna uma função que pega o módulo de destino como argumento e retorna a versão estendida. Dessa forma, você pode estender o widget em locais diferentes sem substituir indesejadas.

Aaron Allen
fonte
Ótimo! Informações úteis. Valeu. Esquecimixin
Khoa TruongDinh
Só consigo ver AWidgetno seu código como se inscrever BWidget?
Rendy Eko Prastiyo 02/03
1
BWidgetseria implementado da mesma forma que AWidget.
Aaron Allen
Obrigado senhor, eu implementei seu código e ele funciona como deveria.
Rendy Eko Prastiyo #
@AaronAllen, +1 Nice info.
Rakesh Jesadiya
2

Verifique se o módulo personalizado foi carregado após os outros

<sequence> para garantir que os arquivos necessários de outros componentes já estejam carregados quando o componente for carregado

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 fazer o check-in app/etc/config.php. Seu módulo personalizado deve ser "nível mais baixo" que outros.

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

Podemos remover o módulo personalizado da setup_moduletabela. E, em seguida, execute o comando setup upgrade novamente para reordenar a sequência do módulo.

Precisamos garantir que o js personalizado seja "nível mais baixo" do que outros requirejs-config.js.

pub / static / _requirejs / frontend / Magento / luma / pt_BR / 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);

Declare o módulo B

Como o widget A foi "substituído", o widget Magento padrão já. Portanto, no Módulo B, precisamos carregar o widget A e "substituí-lo" .

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;
});

Afinal, precisamos executar a implantação de conteúdo estático novamente.

Podemos ler mais aqui: https://learn.jquery.com/jquery-ui/widget-factory/extending-widgets/#using-_super-and-_superapply-to-access-parents

Khoa TruongDinh
fonte
1
Obrigado pela sua resposta. Eu implementei esse método algum dia atrás e, sim, funcionou. Mas então, eu me encontro em um problema em que o AModule deve ser independente do BModule, de modo que, quando eu desabilito o AModule, o BModule ainda deve funcionar, vice-versa. Aqui é onde sua resposta infelizmente não pode lidar com esse problema.
Rendy Eko Prastiyo