Skip to Content

Components

About

The code below shows three different approaches to load component in Magento. Any of these approaches may be used by Magento developer:

<!-- 1. data-mage-init -->
<div data-mage-init='{"Vendor_Module/js/component": {}}'></div>

<!-- 2. x-magento-init -->
<script type="text/x-magento-init">
{
    ".class-name": {
        "Vendor_Module/js/component": {}
    }
}
</script>

<!-- 3. inline `require` call -->
<script>
require(['Vendor_Module/js/component'], function () {
    //
});
</script>

While the code above is working in Luma out of the box, in Breeze you need to register Vendor_Module/js/component component and its dependencies using breeze_default.xml file.

Component registration

Minimal example

<referenceBlock name="breeze.js">
  <arguments>
    <argument name="bundles" xsi:type="array">
      <item name="default" xsi:type="array">
        <item name="items" xsi:type="array">
          <!-- Vendor_Module/js/component is a component name used in DOM structure -->
          <item name="Vendor_Module/js/component" xsi:type="array">
            <!-- Path to the js file with component declaration -->
            <item name="path" xsi:type="string">Vendor_Module/js/breeze/file</item>
          </item>
        </item>
      </item>
    </argument>
  </arguments>
</referenceBlock>

In result of code above, Breeze will load Vendor_Module/js/breeze/file.js.

<referenceBlock name="breeze.js">
  <arguments>
    <argument name="bundles" xsi:type="array">
      <!-- Bundle name -->
      <item name="default" xsi:type="array">
        <item name="items" xsi:type="array">
          <!-- Component name -->
          <item name="Vendor_Module/js/component" xsi:type="array">
            <!-- Path to our JS file -->
            <item name="path" xsi:type="string">Vendor_Module/js/breeze/file</item>
            <!-- Config paths to check before injecting JS file -->
            <item name="enabled" xsi:type="helper" helper="Swissup\Breeze\Helper\Config::isAnyEnabled">
              <param name="0">config/path1/enabled</param>
              <param name="1">config/path2/enabled</param>
            </item>
            <!-- Load this file when bundle is active. Used when merge/bundling is disabled. -->
            <item name="autoload" xsi:type="boolean">true</item>
            <!-- JS files to load before our file -->
            <item name="import" xsi:type="array">
              <item name="dependency" xsi:type="string">Vendor_Module/js/lib</item>
            </item>
            <!-- Component names that we declare inside our JS file -->
            <item name="export" xsi:type="array">
              <item name="fullname" xsi:type="string">Vendor_Module/js/component</item>
              <item name="shortname" xsi:type="string">vendorModule</item>
            </item>
            <!-- Dynamic JS: do not inject the file until one of the following condition is met -->
            <item name="load" xsi:type="array">
              <item name="onInteraction" xsi:type="boolean">true</item>
              <item name="onRequire" xsi:type="boolean">true</item>
              <item name="onEvent" xsi:type="array">
                <item name="0" xsi:type="string">click .selector</item>
                <item name="1" xsi:type="string">customEventName</item>
              </item>
              <item name="onReveal" xsi:type="array">
                <item name="0" xsi:type="string">selector1</item>
                <item name="1" xsi:type="string">selector2</item>
              </item>
              <item name="onDom" xsi:type="array">
                <item name="0" xsi:type="string">selector1</item>
                <item name="1" xsi:type="string">selector2</item>
              </item>
            </item>
          </item>
        </item>
      </item>
    </argument>
  </arguments>
</referenceBlock>

Bundle name

The following bundles are available:

Additionally, you can declare your own bundles. Just make sure that its name is unique to prevent collisions with other third-party modules.

Dynamic component

When you add <item name="load" xsi:type="array"> section to the component registration, Breeze will not load this js file with bundle. Instead, it will dynamically inject it after certain condition is met.

onInteraction

After the first user interaction (mousemove, scroll, click, keydown):

<item name="load" xsi:type="array">
  <item name="onInteraction" xsi:type="boolean">true</item>
</item>

onRequire

After require()|define() will ask for this component:

<item name="load" xsi:type="array">
  <item name="onRequire" xsi:type="boolean">true</item>
</item>

onEvent

When one of js events will be triggered:

<item name="load" xsi:type="array">
  <item name="onEvent" xsi:type="array">
    <item name="0" xsi:type="string">click .selector</item>
    <item name="1" xsi:type="string">customEventName</item>
  </item>
</item>

onReveal

When one of matched elements is about to enter the viewport:

<item name="load" xsi:type="array">
  <item name="onReveal" xsi:type="array">
    <item name="0" xsi:type="string">selector1</item>
    <item name="1" xsi:type="string">selector2</item>
  </item>
</item>

onDom

When one of matched elements is found in DOM structure:

<item name="load" xsi:type="array">
  <item name="onDom" xsi:type="array">
    <item name="0" xsi:type="string">selector1</item>
    <item name="1" xsi:type="string">selector2</item>
  </item>
</item>

Component declaration

Just like in Luma, every component is declared using $.widget, Component.extend, plain object, or function notation. The only difference that you must add component property with proper component name (The name that is used in DOM structure).

Widget

define(['jquery'], ($) => {
  'use strict';

  $.widget('uniqueWidgetName', {
      component: 'Vendor_Module/js/component', // This line is required in Breeze
      create: function () {
          console.log(this.element);
          console.log(this.options);
      }
  });
});

UI Component

define(['uiComponent'], (Component) => {
  'use strict';

  return Component.extend({
    component: 'Vendor_Module/js/component', // This line is required in Breeze
    create: function () {
        console.log(this.element);
        console.log(this.options);
    }
  });
});

Plain object

define([], () => {
  'use strict';

  return {
    component: 'Vendor_Module/js/component', // This line is required in Breeze
    'Vendor_Module/js/component': function () {
      //
    }
  };
});

Plain Function

define([], () => {
  'use strict';

  var cmp = function () {
    //
  };

  cmp.component = 'Vendor_Module/js/component'; // This line is required in Breeze

  return cmp;
});

Programmatic usage

// Create component
require(['Vendor_Module/js/component'], (component) => {
  var instance = component(settings, element);
});

// Retrieve previously created component
require(['jquery'], ($) => {
  // get widget component instance
  var instance = $(el).uniqueWidgetName('instance');

  // or get the component of any type
  var instance = $(el).component('Vendor_Module/js/component');
});