Are you looking for some guidelines on how  to create new JavaScript functions in Icinga Web 2?  This article will show you the necessary structure your function should have in order to compile correctly with Icinga.

If you’ve already looked at some example functions within the existing Icinga JS code, you will have noticed that all these functions follow the Design Patterns structure.

What is a Design Pattern?

Design patterns are advanced object-oriented solutions to commonly occurring software problems.  The bane of every developer is writing readable, maintainable, and reusable code, and design patterns are crucial for solving this challenge.  Solid design patterns are the basic building block for maintainable software applications. In other words, a design pattern is a reusable software solution to a specific type of problem that occurs frequently when developing software.

Design Patterns in JavaScript

Talking about Object Oriented solutions related to JavaScript can be confusing, as JavaScript does not really have the concept of a “class”; a more correct term is “data type”. JavaScript is an object-oriented language where objects inherit from other objects in a concept known as prototypical inheritance. This means that a data type can be created by defining what is called a constructor function.

Let’s go through an Icinga function to see how this works:

// Definition of a constructor function
var EventListener = function (icinga) {
 this.icinga = icinga;
 this.handlers = [];

// Adding an "Event Handler" to the new function EventListener
EventListener.prototype.on = function(evt, cond, fn, scope) {
 if (typeof cond === 'function') {
 scope = fn;
 fn = cond;
 cond = 'body';
 this.icinga.logger.debug('on: ' evt '(' cond ')');
 this.handlers.push({ evt: evt, cond: cond, fn: fn, scope: scope });

What does each element represent?

The constructor function

A constructor function is no different than any other function, in fact the term “constructor function” is just a common nomenclature that suggests that the function will create new properties on the object being created (represented by this).


First of all note that EventListener.prototype.on is not really a part of the EventListener function. Usually this code is called when the web page is loaded, which makes the EventListener function available to be called. After the EventListener is created, the “on” property is then created. Usually when you invoke an object using the new keyword, JS creates a new object, passes it in as this to the constructor function (letting that function do to it whatever it wants) and then (and this is the important part), it takes the object instance that is pointed to by that function’s prototype property and assigns it as the prototype for that object.  So “on” isn’t really a direct property of EventListener , because “on” belongs to its prototype.

What is happening here, instead, is when we ask for EventListener .on, it checks to see if EventListener has a property named on, and if it does it returns it.  If not, it asks EventListener ‘s prototype if it has an on property. It continues doing this all the way up the prototype chain until it either finds the matching property or finds an object with a null prototype.  If it doesn’t find the property in the prototype chain it will return undefined. A prototype chain is basically a linked-list of objects pointing backwards to the object from which each one inherits.

Multiple Levels of Inheritance

var ApplicationState = function (icinga) {
 Icinga.EventListener.call(this, icinga);
 this.on('rendered', this.onRendered, this);
 this.icinga = icinga;

ApplicationState.prototype = new Icinga.EventListener();

As you can see from the example above, sometimes Icinga’s functions use multiple levels of inheritance. This happens when they want to create  a constructor function that “inherits” from another constructor function. In this way you can easily reuse existing functions.

Here I’ve given you an overview of the right way to implement new JavaScript functions for Icinga Web 2. Now you should be able to use these patterns in your own functions.  Note that you can use OOP in even small and medium applications, not just complex functions.

Valentina Da Rold

Valentina Da Rold

Hi, I'm Valentina and I'm a Frontend Developer at Wuerth Phoenix. I started out my career applying my Cryptography skills to coding, but really quickly fell in love with the web. I have been making websites and applications since 2012 and I still can't get enough of it. Along the way I found a passion for front-end development, and I use this passion to create interfaces that solve problems. When I'm not creating beautiful solutions, I enjoy cooking or doing sport, while listening to beautiful music.
Valentina Da Rold

Latest posts by Valentina Da Rold (see all)