2

I have been experimenting with a custom module with KnockoutJs on the frontend in M2.

I've created two components: a ProductPackage and a ProductPackagePopop. Functionally, the ProductPackage triggers a modal that renders some details about the package's children.

These two components share quite the same logic which I would like to share between the components. For example, both have a function initTranslation which retrieves the right translations for this store id.

Since I am new to the magento2 Knockout implementation, is there some way to create a base component from which my two components inherit the shared logic? Or a trait like in PHP. I've looked at mixins, but it seems to me it's more fit to extend external is.

define(['uiComponent'], function (Component) {

    return Component.extend({
        store_id: 0,

        initialize: function (config) {
            this.store_id = config.store_id;
            this.initTranslations(config.productPackage);
        },
        initTranslations: function (productPackage) {
          //some logic here
        },
        children: function(){
         // retrieves children
        }


    });
});

I've found this: https://stackoverflow.com/questions/16569810/knockout-viewmodel-base-class-javascript-inheritance , but I find it hard to fit that in the M2 Knockout/RequireJs wrapper.

3

To do this, you need to create basically 3 components.

  1. Your base component. I am calling this BasePackage.
  2. ProductPackage component
  3. ProductPackagePopop component.

Now make ProductPackage and ProductPackagePopop extend from your base component BasePackage.

So inaction, if your module is My_Example. Then your components should somewhat look like below:

Your base component

File: app/code/My/Example/view/frontend/web/js/base-package.js

define(['uiComponent'], function (Component) {

return Component.extend({
    // this is your common method
    initTranslations: function (productPackage) {
      //some logic here
    },
    
    // put your common methods here in this base component
});

Your ProductPackage component

File: app/code/My/Example/view/frontend/web/js/product-package.js

define(['My_Example/js/base-package'], function (BasePackageComponent) {

return BasePackageComponent.extend({
    initialize: function (config) {
        this.store_id = config.store_id;
        this.initTranslations(config.productPackage);
    },
});

Here this component now extends from the BasePackage component. Due to this this.initTranslations() will be referred from the BasePackage component unless you define the same method inside your children's component such as this.

If in case, you need to define the same method inside this component, then calling this._super() will be invoking the parent method.

Your ProductPackagePopop component.

In a similar line, this component will look like the above.

File: app/code/My/Example/view/frontend/web/js/product-package-popop.js

define(['My_Example/js/base-package'], function (BasePackageComponent) {

return BasePackageComponent.extend({
    initialize: function (config) {
        this.store_id = config.store_id;
        this.initTranslations(config.productPackage);
    },
});

I hope you get the idea.

1
  • 1
    Nice! Thank you, i was experimenting with mixins, which worked, but it seemed like not the right tool for the job. This is exactly what i meant. Thanks! May 24 '21 at 10:22

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.