# Frontend components

Frontend components are JavaScript modules that can be required directly through the HTML markup of
your view, to provide additional functionality for the user. Although its best practice to
make all features available without JavaScript, these components can be used to provide a richer
and more comfortable user experience in case JavaScript is available.

There is a certain set of frontend components which come directly with the Icinga2-Web core application,
but it is also possible to define new components directly in Icinga2-Web modules.


## How do components work?

Components are defined in JavaScript files that provide a set of functionality that will be added to the
targeted HTML node. Icinga2-Web uses [RequireJS](http://requirejs.org) to load
all frontend components, so each frontend component is in fact
[defined exactly like a RequireJS-Module](http://requirejs.org/docs/api.html#define) .

The important difference to plain RequireJS is, that the loading and execution of these components is
done automatically through the HTML markup. The attribute *data-icinga-component* in a DIV
element will indicate that this element is a container for a frontend component and will trigger
the component loader to create a component instance for this HTML node. The component loader
keeps track of all available components and makes it possible to retrieve this instance when needed.


### Component names

A component name consists of two parts: the namespace and the name of the component itself. The component
is named exactly like its JavaScript file, while the namespace is the name of the Icinga2-Web module that contains
the component. Each Icinga2-Web module can contain its own components in the folder *public/js*.

   <module>/<component>


NOTE: The namespace used for modules defined in the Icinga2-Web core application is "app". In opposition to
the modules the core application keeps its modules located in *public/js/icinga/components*
instead of *public/js*.


#### Example Names


The full name for the component *modules/monitoring/public/js/someComponent.js* in the module "monitoring" would be:

    "monitoring/someComponent"


The full component name for the component *public/js/icinga/components/datetime.js* in the Icinga2-Web
 core application would:

   "app/datetime"


## Creating a component

As described in the chapters above, components are defined exactly like RequireJS modules, but
with the additional requirement that they must always return a class constructor. The component below will
search all date pickers, set the time format and create a JavaScript date picker when there is no native one
available.

    /**
     * Ensures that our date/time controls will work on every browser (natively or javascript based)
     */
    define(['jquery', 'datetimepicker'], function($) {
        "use strict";

        var DateTimePicker = function(target) {
            $(target).find('.datetime input')
                .attr('data-format', 'yyyy-MM-dd hh:mm:ss');

            $(target).find('.datetime')
                .addClass('input-append')
                .append('<span class="add-on">' +
                    '<i data-time-icon="icon-time" data-date-icon="icon-calendar"></i></span>')
                .datetimepicker();
        };
        return DateTimePicker;
    });


## Loading a component

The following code will load the module *datetime*, which will ensure that there is always a datetime-picker
with right time-format available.

    <div id="date-time-picker" data-icinga-component="app/datetime">

        <div class="datetime">
            <input data-format="dd/MM/yyyy hh:mm:ss" type="text"/>
        </div>

    </div>


### Component ids

When an ID is assigned to the HTML element, it will be used by the component loader to reference this
component. Otherwise an ID in the form "icinga-component-<ID>" will be created and the ID attribute in the
HTML Element will be updated accordingly.


### Component "target"

The div-element with the *data-icinga-component* will be used as the "target" for the loaded component,
which means that the component will perform its actions on this HTML node.



# Retrieving a component

Sometimes it can be necessary to retrieve the instances of the components itself, for example when they implement
additional functions that can be called. The component loader is available in the Icinga object and can be used
to retrieve component instances using their ID or their full component name.


## By component id

    var component = Icinga.components.getById("component-id");
    component.doSomething();


## By full component name

    var components = Icinga.components.getByType("app/datetime");
    // ... do something with every component of the type app/datetime

## All components

    var components = Icinga.components.getComponents();
    // ... do something with every component
