# Adding new JavaScript

**The `LokiTheme_LumaComponents` module applies various JavaScript components and Alpine.js components to HTML areas where Luma needs it.**

## Adding vanilla JS components without template overrides
To add plain JavaScripts components, without requiring template overrides, we can make use of the `LokiTheme\LumaComponents\Observer\AddJsComponents` observer, which allows for creating DI XML type definitions on its constructor argument `componentDefinitions`: An array with the key representing a block name (in the XML layout) and the value representing a JavaScript component name:

```xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="LokiTheme\LumaComponents\Observer\AddJsComponents">
        <arguments>
            <argument name="componentDefinitions" xsi:type="array">
                <item name="foo.bar" xsi:type="string">FooBar</item>
            </argument>
        </arguments>
    </type>
</config>
```

This adds an identifier `data-js-component="FooBar"` to the HTML element, so that some JavaScript is able to refer to it as follows:
```js
const componentElement = document.querySelector('[data-js-component="FooBar"]');
```

A JavaScript component could be a simple self-executing function:

```js
(function() {
    const componentElement = document.querySelector('[data-js-component="FooBar"]');
})();
```

If you are depending on an Alpine.js store, make sure to listen for `alpine:init`:

```js
document.addEventListener('alpine:init', () => {
    const componentElement = document.querySelector('[data-js-component="FooBar"]');
});
```

## Adding Alpine.js components without template overrides
To add Alpine.js components cleanly, without requiring template overrides, we can make use of the `LokiTheme\LumaComponents\Observer\AddAlpineComponents` observer, which allows for creating DI XML type definitions on its constructor argument `componentDefinitions`: An array with the key representing a block name (in the XML layout) and the value representing an Alpine component name:

```xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="LokiTheme\LumaComponents\Observer\AddAlpineComponents">
        <arguments>
            <argument name="componentDefinitions" xsi:type="array">
                <item name="foo.bar" xsi:type="string">FooBar</item>
            </argument>
        </arguments>
    </type>
</config>
```

For each Alpine component name (like `LumaTabs`) a new block needs to be created via the XML layout with a PHTML template defining the Alpine component:
```js
document.addEventListener('alpine:init', () => {
    Alpine.data('FooBar', () => ({
        init() {}
    }));
});
```

This only works up to a certain level. The `x-data` HTML attribute allows for an Alpine component to be initialized. But the rest of the PHTML template lacks Alpine.js bindings (`x-html`, `@change`, etcetera) and because of this, the Alpine components often lack flexibility and fall back to ugly JavaScript scenarios. This is where template overrides might be needed.

## Removing components again
It might be that in your own specific theme, you don't want to use a JavaScript or Alpine.js component for a specific block, simply because you are creating a different implementation. The automatic insertion of components can be undone again by setting the component value to `false`:

For plain JavaScript components:
```xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="LokiTheme\LumaComponents\Observer\AddJsComponents">
        <arguments>
            <argument name="componentDefinitions" xsi:type="array">
                <item name="foo.bar" xsi:type="boolean">false</item>
            </argument>
        </arguments>
    </type>
</config>
```

For Alpine.js components:
```xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="LokiTheme\LumaComponents\Observer\AddAlpineComponents">
        <arguments>
            <argument name="componentDefinitions" xsi:type="array">
                <item name="foo.bar" xsi:type="boolean">false</item>
            </argument>
        </arguments>
    </type>
</config>
```
