To build a simple Loki Component, you will need to create a template-block in the XML layout, create a template and add a Loki-specific file etc/loki_components.xml. Once this is done, the block will automatically be transformed into a Loki Component with Alpine.js bindings. Calling upon the Alpine method post() will generate an AJAX request to Magento, after which all so-called targets will be updated.
A simple component could first be defined by using the XML layout:
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:View/Layout:etc/page_configuration.xsd">
<update handle="loki_components"/>
<body>
<referenceContainer name="after.body.start">
<block
name="loki-components.example"
template="YireoTraining_ExampleLokiComponent::example.phtml"/>
</referenceContainer>
</body>
</page>
Note that the handle loki_components is added, to make sure AlpineJS and all of the specific Loki scripts are initialized.
Make sure to give thought to your block name, because it will be used as a unique identifier and the name of your Loki Component.
etc/loki_components.xmlNext, a file etc/loki_components.xml upgrades your block to an actual component. Note that the name of the component is equal to the name of your block:
<?xml version="1.0" encoding="UTF-8" ?>
<components xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Loki_Components:etc/loki_components.xsd">
<component name="loki-components.example" />
</components>
Next, a PHTML template example.phtml could be including a simple button:
<div>
<button @change="post">Refresh</button>
</div>
This tries to call a post() method in an Alpine component that you did not write. This is important to note. However, simply because you defined your block to be a Loki Component, the framework transforms your PHTML template output into the following:
<div id="loki-components-example"
x-data="LokiComponent"
x-title="LokiComponentsExample"
class="loki-components-example relative">
<script ref="initialData" type="text/x-loki-init">{"value":null}</script>
<button @change="post">Click</button>
</div>
As you can see, the Loki Components module changes the PHTML template as follows:
id and classx-data refers to the AlpineJS component LokiComponent containing the method post();x-title refers to the AlpineJS component ID (while this specific HTML attribute is also used by the DevTools)The additional HTML <script> tag is generated too. It is not a JavaScript tag, but instead a JSON container that is used to insert data into the AlpineJS component instance via the init() method. The shown data here is a simplified version though.
An important note of this simple component is that it does not save any data on the server side. The post() method simply makes an AJAX call and the current PHTML template will refresh. To save data on the server, we actually need to introduce a ComponentRepository class, which is explained on the next page "Adding a ComponentRepository class"
x-data and x-title?With x-data, an Alpine.js component is instantiated. With x-title, you only give a cosmetic title to the component, which is nice in the Alpine.js DevTools browser plugin.
The Loki Checkout tries to never use local data (x-data='{"foo":"bar"}') or functions (x-data="foobar()") to instantiate components. Instead, a JavaScript snippet is added to instantiate the component data via Alpine.data('FooBar', () => {}); so that x-data="FooBar" is enough to instantiate the component. This separation is choosen to allow for future security restrictions (like PCI Compliance via CSP rules).
However, the Alpine.js data might be as generic LokiCheckoutFieldComponent, while the actual live component is dealing with a specific street1 field instead. To help you navigate through components in the DevTools, the x-title attribute is added with a value like LokiCheckoutShippingAddressStreet1.