jdPerez Logo Header
8 minutos de lectura | 24/07/2024

Crear observable disponible entre ficheros JS

Vamos a explicar algo sencillo y muy práctico para el checkout de Magento2, un observable disponible entre todos los ficheros JS donde lo definamos.

Como sabemos, en Magento2, el checkout está compuesto por ficheros de JS independiente y algunos dependientes de un fichero padre. Pero... ¿y si necesitamos escuchar una variable que dependa de cierta acción?, por ejemplo, supongamos que el cliente decide que su dirección de facturación sea diferente a la de envío, y en este caso, queremos añadir en el top un mensaje de advertencia de que sería obligatorio en este caso añadir el VAT Number para la factura, pues bien, veamos como hacerlo.

Vamos a trabajar directamente sobre el tema de Luma, no sería necesario crear un módulo para esto.

Nos crearíamos un modelo como este:

app/design/frontend/Magento/luma/Magento_Checkout/web/js/model/billing-information-changed.js

define([
    'ko'
], function (ko) {
    'use strict';
    return ko.observable(false);
});

A su vez creamos un componente para mostrar el mensaje:

app/design/frontend/Magento/luma/Magento_Checkout/web/js/view/billing-information-message.js

define([
    'ko',
    'uiComponent',
    'Magento_Checkout/js/model/billing-information-changed'
], function (
    ko,
    Component,
    modelBillingInformationChanged
) {
    'use strict';
 
    return Component.extend({
        defaults: {
            template: 'Magento_Checkout/view/billing-information-message'
        },
 
        showMessage: ko.observable(modelBillingInformationChanged()),
 
        initObservable: function () {
            var self = this;
            modelBillingInformationChanged.subscribe(function (newValue){
                if (newValue !== undefined) {
                    self.showMessage(newValue);
                }
            });
 
            return this._super();
        }
    });
});

Aquí, como podemos ver tenemos definido nuestro modelo, al cual le haremos un subscribe para estar pendientes de si este cambia que a su vez cambie la variable showMessage que usaremos para visualizar o no el template.

app/design/frontend/Magento/luma/Magento_Checkout/web/template/view/billing-information-message.html

<div class="billing-information-message" data-bind="visible: showMessage">
    <span>Se está eligiendo una dirección de facturación nueva!</span>
</div>

Por último, añadiremos nuestro componentes dentro del layout, lo meteremos directamente en el display area de messages que ya tenemos en el onepage.html:

app/design/frontend/Magento/luma/Magento_Checkout/layout/checkout_index_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="checkout" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.root">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="components" xsi:type="array">
                        <item name="checkout" xsi:type="array">
                            <item name="children" xsi:type="array">
                                <item name="billing-information-message" xsi:type="array">
                                    <item name="component" xsi:type="string">Magento_Checkout/js/view/billing-information-message</item>
                                    <item name="displayArea" xsi:type="string">messages</item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

Ahora bien, por último necesitamos hacer un mixin del billing-address.js para ver en que momento se hace uso de una nueva dirección de facturación:

app/design/frontend/Magento/luma/Magento_Checkout/requirejs-config.js

var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/view/billing-address': {
                'Magento_Checkout/js/view/billing-address-mixin': true
            }
        }
    }
}

app/design/frontend/Magento/luma/Magento_Checkout/web/js/view/billing-address-mixin.js

define([
    'Magento_Checkout/js/model/billing-information-changed'
], function (
    modelBillingInformationChanged
) {
    'use strict';
 
    var mixin = {
        useShippingAddress: function () {
            modelBillingInformationChanged(!modelBillingInformationChanged());
            return this._super();
        }
    }
 
    return function (target) {
        return target.extend(mixin);
    }
});

y con esto ya lo tendríamos todo, ahora, siempre que se pulse el botón de usar una dirección de facturación diferente a la de envío el mixin se encargará de cambiar el modelo de valor, este a su vez entrará dentro del subscribe que nos modificará el observable que nos permitirá mostrar o no el mensaje, ahora bien, como he explicado, este modelo estará siempre accesible, siempre que definamos Magento_Checkout/js/model/billing-information-changed podremos ver en el subscribe el nuevo valor y hacer lo que queramos con él.