2

I wish to know how the list.html works while displaying the payment methods.

1)How it loops to display the payment methods using below template

list.html

 <div if="isPaymentMethodsAvailable()"
     class="items payment-methods">
    <div repeat="foreach: paymentGroupsList, item: '$group'"
         class="payment-group">
        <div if="getRegion($group().displayArea)().length"
             translate="getGroupTitle($group)"
             class="step-title"
             data-role="title">
        </div>
        <each args="data: getRegion($group().displayArea), as: 'method'" render=""/>


    </div>
</div>
<div ifnot="isPaymentMethodsAvailable()"
     class="no-payments-block"
     translate="'No Payment Methods'">
</div>

list.js

define([
    'underscore',
    'ko',
    'mageUtils',
    'uiComponent',
    'Magento_Checkout/js/model/payment/method-list',
    'Magento_Checkout/js/model/payment/renderer-list',
    'uiLayout',
    'Magento_Checkout/js/model/checkout-data-resolver',
    'mage/translate',
    'uiRegistry'
], function (_, ko, utils, Component, paymentMethods, rendererList, layout, checkoutDataResolver, $t, registry) {
    'use strict';

    return Component.extend({
        defaults: {
            template: 'Magento_Checkout/payment-methods/list',
            visible: paymentMethods().length > 0,
            configDefaultGroup: {
                name: 'methodGroup',
                component: 'Magento_Checkout/js/model/payment/method-group'
            },
            paymentGroupsList: [],
            defaultGroupTitle: $t('Select a new payment method')
        },

        /**
         * Initialize view.
         *
         * @returns {Component} Chainable.
         */
        initialize: function () {
            this._super().initDefaulGroup().initChildren();
            paymentMethods.subscribe(
                    function (changes) {
                        checkoutDataResolver.resolvePaymentMethod();
                        //remove renderer for "deleted" payment methods
                        _.each(changes, function (change) {
                            if (change.status === 'deleted') {
                                this.removeRenderer(change.value.method);
                            }
                        }, this);
                        //add renderer for "added" payment methods
                        _.each(changes, function (change) {
                            if (change.status === 'added') {
                                this.createRenderer(change.value);
                            }
                        }, this);
                    }, this, 'arrayChange');

            return this;
        },

        /** @inheritdoc */
        initObservable: function () {
            this._super().
                    observe(['paymentGroupsList']);

            return this;
        },

        /**
         * Creates default group
         *
         * @returns {Component} Chainable.
         */
        initDefaulGroup: function () {
            layout([
                this.configDefaultGroup
            ]);

            return this;
        },

        /**
         * Create renders for child payment methods.
         *
         * @returns {Component} Chainable.
         */
        initChildren: function () {
            var self = this;

            _.each(paymentMethods(), function (paymentMethodData) {
                self.createRenderer(paymentMethodData);
            });

            return this;
        },

        /**
         * @returns
         */
        createComponent: function (payment) {
            var rendererTemplate,
                    rendererComponent,
                    templateData;

            templateData = {
                parentName: this.name,
                name: payment.name
            };
            rendererTemplate = {
                parent: '${ $.$data.parentName }',
                name: '${ $.$data.name }',
                displayArea: payment.displayArea,
                component: payment.component
            };
            rendererComponent = utils.template(rendererTemplate, templateData);
            utils.extend(rendererComponent, {
                item: payment.item,
                config: payment.config
            });

            return rendererComponent;
        },

        /**
         * Create renderer.
         *
         * @param {Object} paymentMethodData
         */
        createRenderer: function (paymentMethodData) {
            var isRendererForMethod = false,
                    currentGroup;

            registry.get(this.configDefaultGroup.name, function (defaultGroup) {
                _.each(rendererList(), function (renderer) {

                    if (renderer.hasOwnProperty('typeComparatorCallback') &&
                            typeof renderer.typeComparatorCallback == 'function'
                            ) {
                        isRendererForMethod = renderer.typeComparatorCallback(renderer.type, paymentMethodData.method);
                    } else {
                        isRendererForMethod = renderer.type === paymentMethodData.method;
                    }

                    if (isRendererForMethod) {
                        currentGroup = renderer.group ? renderer.group : defaultGroup;

                        this.collectPaymentGroups(currentGroup);

                        layout([
                            this.createComponent(
                                    {
                                        config: renderer.config,
                                        component: renderer.component,
                                        name: renderer.type,
                                        method: paymentMethodData.method,
                                        item: paymentMethodData,
                                        displayArea: currentGroup.displayArea
                                    }
                            )]);
                    }
                }.bind(this));
            }.bind(this));
        },

        /**
         * Collects unique groups of available payment methods
         *
         * @param {Object} group
         */
        collectPaymentGroups: function (group) {
            var groupsList = this.paymentGroupsList(),
                    isGroupExists = _.some(groupsList, function (existsGroup) {
                        return existsGroup.alias === group.alias;
                    });

            if (!isGroupExists) {
                groupsList.push(group);
                groupsList = _.sortBy(groupsList, function (existsGroup) {
                    return existsGroup.sortOrder;
                });
                this.paymentGroupsList(groupsList);
            }
        },

        /**
         * Returns payment group title
         *
         * @param {Object} group
         * @returns {String}
         */
        getGroupTitle: function (group) {
            var title = group().title;

            if (group().isDefault() && this.paymentGroupsList().length > 1) {
                title = this.defaultGroupTitle;
            }

            return title + ':';
        },

        /**
         * Checks if at least one payment method available
         *
         * @returns {String}
         */
        isPaymentMethodsAvailable: function () {
            return _.some(this.paymentGroupsList(), function (group) {
                return this.getRegion(group.displayArea)().length;
            }, this);
        },

        /**
         * Remove view renderer.
         *
         * @param {String} paymentMethodCode
         */
        removeRenderer: function (paymentMethodCode) {
            var items;

            _.each(this.paymentGroupsList(), function (group) {
                items = this.getRegion(group.displayArea);

                _.find(items(), function (value) {
                    if (value.item.method.indexOf(paymentMethodCode) === 0) {
                        value.disposeSubscriptions();
                        value.destroy();
                    }
                });
            }, this);
        }
    });
});
2

Check below example, It might be help to you

File path :

vendor/magento/module-checkout/view/frontend/layout/checkout_index_index.xml

<item name="payments-list" xsi:type="array">
    <item name="component" xsi:type="string">Vendor_ModuleName/js/view/payment/list</item> //Call custom Js here
    <item name="displayArea" xsi:type="string">custom-payment-methods-list</item>
    <item name="config" xsi:type="array">
        <item name="deps" xsi:type="array">
            <item name="0" xsi:type="string">checkout.steps.billing-step.payment.renders</item>
            <item name="1" xsi:type="string">checkout.steps.billing-step.payment.additional-payment-validators</item>
        </item>
    </item>
</item>

vendor/magento/module-checkout/view/frontend/web/template/payment.html

<div id="checkout-payment-method-load" class="opc-payment" data-bind="visible: isPaymentMethodsAvailable">
    <!-- ko foreach: getRegion('custom-payment-methods-list') --> //Call custom template
        <!-- ko template: getTemplate() --><!-- /ko -->
    <!-- /ko -->
</div>

Check this file & change template path

vendor/magento/module-checkout/view/frontend/web/js/view/payment/list.js

template path like this : 'Vendor_ModuleName/payment-methods/list' //Define custom templage path here

This is just example, you need to create a all files in your custom module.

  • the div that you have mentioned above , How do I get the available payment methods – Jaisa May 4 '18 at 9:06
  • Instead of "payment-methods-list" , I wish to add custom template – Jaisa May 4 '18 at 9:07
  • Instead of load default templates for payment methods, I wish to load my custom templates for each payment methods – Jaisa May 4 '18 at 9:10
  • So in payment.html <div id="checkout-payment-method-load" class="opc-payment" data-bind="visible: isPaymentMethodsAvailable"> <!-- ko foreach: getRegion('customtemplate') --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> </div> – Jaisa May 4 '18 at 9:11
  • Can I do like above what i have commented before or will it break any other functionalities? – Jaisa May 4 '18 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.