How to add a button click event listener to an element in B2C demoshop

vparannattilcherul
vparannattilcherul Posts: 16 🧑🏻‍🚀 - Cadet
edited September 2023 in Spryker Development

Hello guys, I've been trying to make this work . I've a requirement where I need to display a button on the payment page clicking on which should collect some data from the form and make a call to a third party api and fetch the response to show something on the frontend. This looks really easy, but I'm not really sure how this should be done in Spryker Yves. Lemme explain the steps I've done. The starting point is src/Pyz/Yves/CheckoutPage/Theme/default/views/payment/payment.twig

  • Created a file named payment.ts in the same directory with this code
import Component from 'ShopUi/models/component';

export default class Payment extends Component {
    protected checkNowButton: HTMLButtonElement;

    protected readyCallback(): void {}
    
    protected init(): void {
       this.checkNowButton = <HTMLButtonElement>this.getElementsByClassName('check-now-button')[0];
       this.mapEvents();
    }

    protected mapEvents(): void {
        this.checkNowButton.addEventListener('click', () => this.onButtonClick());
    }

    protected onButtonClick() {
        console.log('Hello');
    }
}
  • added an index.ts in the same directory
import './payment.scss';
import register from 'ShopUi/app/registry';
export default register(
    'payment',
    () =>
        import(
            /* webpackMode: "lazy" */
            /* webpackChunkName: "form-submitter" */
            './payment'
        ),
);
  • Now I ran the commands npm run yves and docker/sdk console cache:empty-all
  • I'm able to see the code generated in public/Yves/assets/current/default/js/yves_default.payment.js
  • But when I check the frontend http://yves.de.spryker.local/en/checkout/payment, I dont see this file getting loaded.
  • These are the only files which are loaded on the screen

So, I thought that this could be due to the fact that i used /* webpackChunkName: "payment" */ in index.ts. So I tried to use some other webpackChunkName which already exists (I know this is wrong, just tried for checking). Then I was able to see the code inside the file public/Yves/assets/current/default/js/yves_default.form-submitter.js and it was loaded on the frontend as well.

"use strict";
(self["webpackJsonp_yves_default"] = self["webpackJsonp_yves_default"] || []).push([["form-submitter"],{

/***/ "./src/Pyz/Yves/CheckoutPage/Theme/default/views/payment/payment.ts":
/*!**************************************************************************!*\
  !*** ./src/Pyz/Yves/CheckoutPage/Theme/default/views/payment/payment.ts ***!
  \**************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ Payment)
/* harmony export */ });
/* harmony import */ var ShopUi_components_molecules_form_submitter_form_submitter__WEBPACK_IMPORTED_MODULE_0__1 = __webpack_require__(/*! ShopUi/models/component */ "./src/Pyz/Yves/ShopUi/Theme/default/components/molecules/form-submitter/form-submitter.ts");

class Payment extends ShopUi_components_molecules_form_submitter_form_submitter__WEBPACK_IMPORTED_MODULE_0__1["default"] {
  constructor() {
    super(...arguments);
    this.checkNowButton = void 0;
  }
  readyCallback() {}
  init() {
    this.checkNowButton = this.getElementsByClassName('check-now-button')[0];
    this.mapEvents();
  }
  mapEvents() {
    this.checkNowButton.addEventListener('click', () => this.onButtonClick());
  }
  onButtonClick() {
    console.log('Hello');
  }
}

/***/ }),

But still the event listener is not taking effect. Is there any steps am I really missing guys? I dont really find anything in the spryker docs about how to handle it. Also please let me know if there is any other ways to do it without using .ts files (which I'm new to).

Tagged:

Best Answer

  • fsmeier
    fsmeier Senior Software Engineer & Developer Enablement Advocate Sprykee Posts: 1,056 ⚖️ - Guardians (admin)
    Answer ✓

    Heyhey @vparannattilcherul ,

    I am not a frontend expert but I talked to some of my FE colleagues and they gave me some hints:

    payment.twig is a view template, TS will not work there.
    The right approach is to create a new molecule in CheckoutPage module and use it inside payment.twig view, see an example belowCheckoutPage/Theme/default/components/molecules/payment-form-buttonpayment-form-button.twig

    {% extends model('component') %}
    
    {% define config = {
        name: 'payment-form-button',
        tag: 'payment-form-button',
    } %}
    
    {% define data = {} %}
    {% define attributes = {} %}
    
    {% block body %}
        <button type="button" class="{{ config.jsName }}__save">{{ 'Save' | trans }}</button>
    {% endblock %}
    

    payment-form-button.ts

    import Component from 'ShopUi/models/component';
    
    export default class PaymentFormButton extends Component {
        protected checkNowButton: HTMLButtonElement;
    
        protected readyCallback(): void {}
    
        protected init(): void {
            this.checkNowButton = <HTMLButtonElement>this.getElementsByClassName(`${this.jsName}__save`)[0];
    
            this.mapEvents();
        }
    
        protected mapEvents(): void {
            this.checkNowButton.addEventListener('click', () => this.onButtonClick());
        }
    
        protected onButtonClick() {
            console.log('Hello');
        }
    }
    

    index.ts

    import register from 'ShopUi/app/registry';
    export default register(
        'payment-form-button',
        () =>
            import(
                /* webpackMode: "lazy" */
                /* webpackChunkName: "payment-form-button" */
                './payment-form-button'
                ),
    );
    

    payment.twig

    {% include molecule('payment-form-button', 'CheckoutPage') with {
        data: {},
        attributes: {},
    } only %}
    
    • npm run yves
    • console c:e && console t:c:w

    Please let me know if this helped you so I can thank our FE devs again :D

    All the best,

    Florian

Answers

  • fsmeier
    fsmeier Senior Software Engineer & Developer Enablement Advocate Sprykee Posts: 1,056 ⚖️ - Guardians (admin)
    Answer ✓

    Heyhey @vparannattilcherul ,

    I am not a frontend expert but I talked to some of my FE colleagues and they gave me some hints:

    payment.twig is a view template, TS will not work there.
    The right approach is to create a new molecule in CheckoutPage module and use it inside payment.twig view, see an example belowCheckoutPage/Theme/default/components/molecules/payment-form-buttonpayment-form-button.twig

    {% extends model('component') %}
    
    {% define config = {
        name: 'payment-form-button',
        tag: 'payment-form-button',
    } %}
    
    {% define data = {} %}
    {% define attributes = {} %}
    
    {% block body %}
        <button type="button" class="{{ config.jsName }}__save">{{ 'Save' | trans }}</button>
    {% endblock %}
    

    payment-form-button.ts

    import Component from 'ShopUi/models/component';
    
    export default class PaymentFormButton extends Component {
        protected checkNowButton: HTMLButtonElement;
    
        protected readyCallback(): void {}
    
        protected init(): void {
            this.checkNowButton = <HTMLButtonElement>this.getElementsByClassName(`${this.jsName}__save`)[0];
    
            this.mapEvents();
        }
    
        protected mapEvents(): void {
            this.checkNowButton.addEventListener('click', () => this.onButtonClick());
        }
    
        protected onButtonClick() {
            console.log('Hello');
        }
    }
    

    index.ts

    import register from 'ShopUi/app/registry';
    export default register(
        'payment-form-button',
        () =>
            import(
                /* webpackMode: "lazy" */
                /* webpackChunkName: "payment-form-button" */
                './payment-form-button'
                ),
    );
    

    payment.twig

    {% include molecule('payment-form-button', 'CheckoutPage') with {
        data: {},
        attributes: {},
    } only %}
    
    • npm run yves
    • console c:e && console t:c:w

    Please let me know if this helped you so I can thank our FE devs again :D

    All the best,

    Florian

  • vparannattilcherul
    vparannattilcherul Posts: 16 🧑🏻‍🚀 - Cadet

    Hi Florian,

    Thank you very much for the answer. I actually found it that day itself. I was quite doubtful to add the answer here. Was waiting for someone from the spryker team to answer, then I could add my comments here. I've tried this way even before the question was posted. But I was not aware of the requirement of the 'hyphen' usage on the name of the component. The thing is that the config.name parameter always should be separated by a hyphen ('-'). If not, it was not working. So when I tried for the first time, I tried like name: 'payment' and it didn't work, so I asked the question here. But then, i tried with another name with an hyphen as separator, it suddenly worked. So fellow developers, please keep in mind that we always use a hyphen there.

    {% define config = {
        name: 'payment-form-button',
        tag: 'payment-form-button',
    } %}