# Component definitions

**Within the Loki architecture, we are not just simply referring to Alpine components as is. Instead, we talk about components, component data definitions, component types and component partials. One of the reasons for this more advanced approach is to make sure that Alpine.js properties become reusable across components, without duplicating code. The component partials also allow you to merge together desired property objects, offering mixin-like or trait-like behaviour.**

## Different definitions
Because Loki focuses heavily upon the reusability of code, how Alpine components come to being depends upon 4 things:

- Components are regular Alpine components, managed by Alpine.js, including two-way binding with the HTML document;
- Components are based upon component data: The thing that you refer to with `x-data`. With Loki, component data is always defined with `Alpine.data()` and the definitions are placed preferably in the XML layout container `loki-components` (which places them at the bottom of the page).
- Component data is constructed via regular JavaScript objects. With Loki, those objects are separated again from the component data definition itself, as a means to reuse JavaScript objects in multiple component data definitions.
- Last but not least, such a JavaScript object could be just a plain object, but it could also be composed of other objects using ES6 destructuring (`...foobar`). Whenever this happens, the destructured object that is *imported* into the regular object is referred to as a component partial. Component partials are comparable to mixins or traits.

## An example: LokiCheckoutSteps
As an example, there is a checkout component named `LokiCheckoutSteps` (which resembles the component property `id` and the `x-title` attribute. It is initiated with `x-data="LokiFieldComponent"` which shows that there is a component data definition `LokiFieldComponent` somewhere on the page as well.

```html
<div id="loki-checkout-steps" x-data="LokiFieldComponent" x-title="LokiCheckoutSteps">
    <script x-ref="initialData" type="text/x-loki-init">
        {"id": "LokiCheckoutSteps", "name": "LokiFieldComponent", /* ... */}
    </script>
</div>
```

The general data definition `LokiFieldComponent` is used in numerous components and defined with the following:

```js
document.addEventListener('alpine:init', () => {
    Alpine.data('LokiFieldComponent', () => ({
        ...LokiFieldComponentType,
    }));
});
```

As you can see, the data definition of `LokiFieldComponent` fully depends upon an object `LokiFieldComponentType` (which we call a *component type*). This object looks like the following):

```js
const LokiFieldComponentType = {
    ...LokiComponentType,
    fieldName: '',
    fieldValue: null,
    /* ... */
}
```

It is a plain object that uses ES6 destructuring to borrow properties from a more generic `LokiComponentType` and then add its own properties on top of this. The `LokiComponentType` is also known as a component type.

In the case, there is no usage of component partials here.

## Component types vs component partials
An example for a component partial could look like the following:

```js
const LokiExampleComponent = {
    ...LokiComponentType,
    ...LokiTabComponentPartial,
}
```

In this case, a custom component `LokiExampleComponent` is created based on top of the component type `LokiComponentType` *and* the component partial `LokiTabComponentPartial`. As you can see, using a component type and a component partial is the same.

The difference between a component type and a component partial is that with the import of a component type (`...LokiComponentType`) you already have a full-blown component, while the import of a component type (`...LokiTabComponentPartial`) you only get specific behaviour.

## Existing component partials
At this moment, the following component partials exist:

- `LokiTabComponentPartial` for managing tabs;
- `LokiModalComponentPartial` for managing modal popups;
