# Loaders and loading state

**When a LokiComponent is busy with the AJAX call (storing its value in Magento and/or updating HTML elements on the page), the Alpine component allows you to hook into this loading state in various ways.**

## The Alpine property `loading`
Each LokiComponent ships with an Alpine property `loading` which is `false` by default, but which is set to `true` while the POST request is running. Elsewhere, the property `loading` is watched for further functionality. However, you could already show a simple loading text, based on this:

```html
<span x-show="loading">Loading ...</span>
```

A fancier example could be the following:
```php
<div x-cloak x-show="loading" class="<?= $css('inline-block mr-3 w-4 animate-spin fill-white', 'icon') ?>">
    <?= $imageOutput->get('Loki_FieldComponents::images/spinner.svg') ?>
</div>
```

## Setting the `aria-busy` attribute
A single LokiComponent update could also involve a refresh of other HTML attributes on the page. While making the AJAX call, each target is resolved into the corresponding HTML element and the `aria-busy` HTML attribute is set. This also counts for the component itself.

If the HTML element contains a child element that shows some kind of loading image, then this child element could be hidden by default but shown again via CSS based upon this `aria-busy` attribute. A lot of LokiCheckout components use this logic as follows:

```php
<div class="<?= $css('relative') ?>">
    <?= $blockRenderer->html($block,'loki-field-components.utils.loader-overlay') ?>
    ...
</div>
```

Here the `<div>` element equals the root of the Alpine component, where `aria-busy` is set. Next, the block `loki-field-components.utils.loader-overlay` is used to display an image loader. By default, this block has the `display:none` CSS rule set (via the Tailwind class `hidden`).

With the corresponding CSS the loader overlay is shown conditionally:
```css
 [aria-busy] > .loader-overlay {
    display: flex;
}
```

## Setting the `loading` property in other Alpine components
The `post()` method tries to map each target name into another LokiComponent on the page. And if that LokiComponent is found, the `loading` property of that LokiComponent is toggled as well.

This causes the possibility that a single component update triggers multiple loaders on the page.

## Delayed loader with `showLoader`
Above it was already explained how a loader overlay was shown. With many field components, a smaller loader image is shown within the field input itself:

```php
<div x-cloak x-show="showLoader" class="<?= $css('field-loader flex absolute inset-y-0 right-0 pt-1 pr-2', 'loader') ?>">
      <?= $blockRenderer->html($block, 'loki-field-components.utils.loader-small') ?>
</div>
```

Apart from different Tailwind classes, it is the same logic. Except for that a different Alpine property `showLoader` is used. While the `loading` property is set once the AJAX call is initiated, the `showLoader` property toggles only after a slight delay. This delay is set via the property `showLoaderTimeout`. (Note that you can change any property of a LokiComponent via the `getJsData()` method of its ViewModel and with that, the XML layout.)

The reason for this is an esthetic reason: In a production environment, often component updates are fast and take little more than 300ms. If every single change would popup that loader for just a split second, it will confuse users. Because of this, the delayed `showLoader` approach allows for showing the loader only, if the user really needs to be informed of the fact that the update is not instant. 

The default `showLoaderTimeout` is 700ms, which should make for a visually appealing updating experience.

## The CSS class `loading` for fields
A complementary way of styling the loading state of fields is by using the CSS class `loading`. This is added to all components that are derived from the `LokiFieldComponent` component data (or actually derived from the `LokiFieldComponentType` component type).

A simplified version of such a component might look like the following:

```html
<div x-data="LokiFieldComponent" x-title="FooBar">
    <script ref="initialData" type="text/x-loki-init">{}</script>
    <input x-model="value" @change="submit" x-ref="field" class="foobar" />
</div>
```

Here, the `<div>` element serves as the root of an Alpine component `FooBar` which uses the `LokiFieldComponent` component data. The `<input>` element is connected to the Alpine property `value` via `x-model`. And every time the value is changed, it is posted to the server by using `submit()`.

Now note the `x-ref`. Within the component logic, this is used by a watcher on the Alpine property `loading`. Whenever the `loading` value is true, the CSS class `loading` is added. Whenever the `loading` value is false, the CSS class `loading` is removed again.

Additionally, the `aria-busy` attribute and `disabled` attribute are also added to the field.

The resulting HTML while loading might look like the following:

```html
<div x-data="LokiFieldComponent" x-title="FooBar" aria-busy>
    <script ref="initialData" type="text/x-loki-init">{}</script>
    <input x-model="value" @change="submit" x-ref="field" class="foobar loading" aria-busy disabled />
</div>
```
