An applet is a core concept of Fabula. Applets are components from which applications are built.
When an application runs, each applet is used as a template for creating any number of instances. An instance is bound to an element in the HTML DOM of the current web page. The applet’s name determines the class of these elements. Whenever an element of this class is added to the DOM, Fabula creates an instance; whenever the element is no longer present, the corresponding instance is destroyed.
In some sense, applets are similar to classes in object-oriented languages. However, unlike classes in such languages, applets are not data types and, unlike objects, instances are not values.
Every applet has a fixed structure. It consists of up to six sections: model, view, init, receive, events and actions. All the sections are optional and can be in any order. Let’s consider each section.
Model determines the data type of the internal state of an applet instance, i.e. the data associated with the instance. The state is mutable, but its data type never changes.
You may ask, how can data be mutable in a declarative language. The answer is simple: Fabula has no means to directly modify the value of a variable, it can only compute a value that later becomes the new state of an instance. See also our note about classes above.
In addition, model introduces a variable used to refer to the current state in other sections of the applet. Note that the model is ‘private’ to the applet and instances can’t access the state of other instances, whether of the same or other applets.
If the model is omitted, it’s assumed to be null, and no state variable is introduced.
The next section of an applet is called view. The view determines how the state is represented in the user interface. It contains an expression of the string type that converts the state into some (X)HTML code that replaces the content of the corresponding DOM element. This HTML code can contain elements of the classes that are bound to Fabula applets, in which case instances of those applets will be created immediately after the view is applied.
The view is computed and applied when an instance is created (after initialization) and after the state changes as result of receiving a message from one of the input channels.
If the view expression is absent or fails, no change to the HTML content of the DOM element occurs.
Unless the model is absent or null, the state of an instance must be explicitly initialized. The initialization section (init) can use as input the following data:
- the value of the data-arg attribute of the DOM element
- the previous HTML content of the element
- the current time when the instance is created
- random numeric data generated when initializing the instance
These sources can be used for customization of instances.
The value returned by the init expression must satisfy the applet’s model.
The receive section determines how applet instances react on input from user-defined channels. Channels are defined separately by associating a name with some data type. The data type tells what data can be sent to/received from the channel. Channels are the only way in Fabula, apart from global constants, to share data among applets.
The receive section consists of several from clauses; each from clause contains the name of a channel and an expression that computes a new state from the following data:
- the current contents of the channel
- the previous state
- the current time when the data were received
- random numeric data
When the receive-from expression fails, the state doesn’t change.
Applets can emit actions that change the state of the environment, such as sending data to a channel or asynchronous AJAX requests. There are two ways to emit actions: in response to end-user events or in response to state changes.
The events section sets the reaction to user events, such as clicking inside the element or submitting a form. The result of each event expression is an action that will be performed by the environment unless the expression fails.
The actions section contains expressions that return actions and will be evaluated after the initialization and every time the state changes. Only those actions that were computed successfully are performed, the failed expressions are ignored.
For more details about applets, read Fabula Language Reference built into Fabula Project Builder.