Are you enjoying the extensions? Did you like the support? Help others decide.

Leave a review
27Mar2023
Information
Print

Coding for Joomla 4: the new loader

Information
First published September 17, 2020
7992 hits -
 

Joomla 4 is catching up with the new (and not so new) web technologies, technologies that are now widely supported by most modern browsers. One of these techniques is Web Components. Web components allow developers to reuse custom elements on a web page or web app without the fear of code collusion.

The Joomla 4 loader is now available as a web component.

The Joomla 3 (ajax) loader

The Joomla 3 loader
The Joomla 3 loader

Using the loader is as simple as making sure it is available on the page. Basically, you would call Joomla.loadingLayer('load'); on the loading of a page, then Joomla.loadingLayer('show'); whenever the loader needs to be visible.
I have started using that technique on long tasks, for instance the import of data into the system. The loader starts on submitting a form and while it waits for the task return, the loader plays in the foreground. The refresh of the page then stops it automatically. There are many possible other uses for a loader, especially when initiating long Ajax tasks.

The Joomla 4 (ajax) loader

You can use the new Joomla 4 loader (or spinner) in the same way, but calling and using it is a bit different.

The Joomla 4 loader
The Joomla 4 loader

Setting the stage

Joomla web components can be found under media/system/js. Joomla 4 introduced web assets. Web assets are very powerful in the sense that you now have a knowledge base (defined as a Json file at media/system/) of how the system javascript libraries are related with each other. Web components are listed and made available as assets as much as any other library like jQuery. The system is aware of all available assets. Then it is just a matter of calling that asset to 'attach' it to a page (web components are loaded asynchronously).

$wam = Factory::getApplication()->getDocument()->getWebAssetManager();
$wam->useScript('webcomponent.core-loader');

Web component assets are prefixed with webcomponent. The loader asset name is core-loader.

Starting the loader

Now that the loader is available, it needs to be added to the document via the DOM (Document Object Model) to be visible. In pure javascript, you can do it like this:

let spinner = document.createElement("joomla-core-loader");
document.body.appendChild(spinner);

Here, the loader is added to the body of the document, but it can be attached to any element via the DOM.

Note that the loader can be added to a page simply with <joomla-core-loader></joomla-core-loader>.

Removing the loader

If you started the loader on a page that is waiting for a refresh, you won't need to remove the loader from the page 'physically'. However, if you are using it to give some sort sort of feedback to users during an Ajax call, you will need to remove the loader once the task has finished.

let spinner = document.querySelector('joomla-core-loader');
spinner.parentNode.removeChild(spinner);

Here, we look for the loader on the page (in case we lost the handle of it) and remove it from its parent node.

Form example

The following example is a code snippet of a component's page in the administrator console. The page loads a form and has associated tasks. Every task will be time consuming and to offer proper feedback, the loader is called and shown when the form is submitted.

$wam = Factory::getApplication()->getDocument()->getWebAssetManager();
$wam->useScript('webcomponent.core-loader');
$wam->addInlineScript('
    Joomla.submitbutton = function(task) {
        spinner = document.createElement("joomla-core-loader");
        document.body.appendChild(spinner);
        Joomla.submitform(task);
    }
');

The loader is removed automatically when the page refreshes.

Ajax example

This time the submission is done via Ajax.

$wam = Factory::getApplication()->getDocument()->getWebAssetManager();
$wam->useScript('webcomponent.core-loader');
$wam->addInlineScript('
    Joomla.submitbutton = function(task) {
        Joomla.submitform(task);
    }
    Joomla.submitform = function(task) {
        document.body.appendChild(document.createElement("joomla-core-loader"));
        Joomla.request({
            type : "POST",
            url : "index.php?option=com_myextension&view=myview&format=json",
            dataType : "json",
            onSuccess: function (response, xhr) {
                response = JSON.parse(response);
                var spinner = document.querySelector("joomla-core-loader");
                spinner.parentNode.removeChild(spinnerElement);
                if (response.error) {
                    console.log("response error");
                } else {
                    if (response.data) {
                        console.log("response success");
                    }
                }
            },
            onError : function (xhr) {
                var spinner = document.querySelector("joomla-core-loader");
                spinner.parentNode.removeChild(spinnerElement);
                console.log("ajax error");
            }
        });
        return false;
    };
');

For more information on web components and web assets, you will find great explanations on the Joomla documentation website.