Before you create a module, you should become familiar with the default module, the directory structure of modules, and module configuration options.
Components are an important part of modules. A component is a content archetype that editors use to create content. BoundComponents are also discussed here. BoundComponents bind one component to another component.
The default module contains common content definitions, rendering templates, resource bundles, and static assets. The module is deployed by default and is used as the basis for many modules.
The module includes a set of features and components, providing base Jahia template functionality:
Jahia Modules uses the Maven 2 directory structure (see Maven Standard Directory Layout).
src
| + main
| + java
| + resources
| + webapps
| + site
The Jahia directory is structured like this:
webapps
| + javascript - contains all javascripts for the module
| + css - contains all css for the module
| + resources - contains all resources for the module
| + icons - contains all icons for the module content definitions
| + OSGI-INF - contains OSGi descriptors (for example, OSGi Blueprint)
| + META-INF
| + spring - Spring XML files
| - definitions.cnd - definitions for the module
| - rules.drl - module rules
| - import.xml - content imported when the module is loaded the first time
When you name your icons and resources, consider the following naming practices:
":"
with "_"
jnt:news
needs a jnt_news.png
iconDepending on your needs, you might want to parameterize some aspects of you modules to customize it for your deployment environment. You have several options to do so as shown below.
Sometimes you want to be able to deploy OSGI configuration files at when you deploy modules. You can do so by adding your configuration files into your module source folder under /src/main/resources/META-INF/configurations
.
The following example is from the Elasticsearch - search provider module.
This automatically deploys the configuration files in the /digital-factory-data/karaf/etc
folder. The OSGI framework automatically registers the configuration during runtime.
Note that a configuration file is overriden each time the module is deployed. This is useful if the configuration file needs to evolve in future versions of your module. If you want to avoid the override of the configuration file during module upgrade, you need to start the first line of your configuration file with the # default configuration
marker.
The following example is from the Elasticsearch - search provider module.
Your module components can depend on Spring beans that can be configured through an XML descriptor found in your module's META-INF/spring/<module-name>.xml
file. Here you can define beans for your components, inject other components (for example, Jahia services), or specify properties that will be resolved when Jahia instantiates the components in your module. Please refer to the Spring documentation for more details.
A component is a content archetype that editors use to create content. Components appear in the left panel selector and can be dragged to an area inside a page.
Components can be declared in a module through a node type definition. All components that are declared in a module are deployed to a tree in the JCR, under the /templateSet node. For every node type definition found, a jnt:component
node is created. Components are organized in components folder of type jnt:componentFolder
. An administrator can browse these nodes using Jahia Tools.
Components are organized by inheriting from special mixin types. Any module can create a new component folder by creating a mixin type inheriting from jmix:droppableContent
.
For each mixin type that inherits from jmix:droppableContent
, like jmix:basicContent
, a component folder is displayed. If a type inherits from a mixin derived from jmix:droppableContent
, it will be stored in the corresponding component folder. Components that do not inherit from jmix:droppableContent
are stored in a folder named nonDroppableComponents.
Components, views, and options provided by a module are only available to a site once the module is deployed on it.
Components can inherit from jmix:studioOnly
. These components are intended to be used for template development only. They are available only in the Studio and are not deployed to sites.
You can use roles and permission to restrict access to different components by users or groups. If a user does not have access to a component, it does not appear in the UI in Jahia. However, they can still edit existing nodes based on these components.
By default, rights are inherited from the site. Users who have edit access can use all components. To restrict permissions, remove permissions from the site-privileged group, then add the users or groups who should be able to access the component.
To set rights on a components:
BoundComponents bind one component to another component. For example, you can bind a calendar component to news component and specify that the news list only displays links for days that have a news entry. This can be extended to allow your calendar to interact with any type of list of content. This section shows how:
In your cnd file, your definition should inherit the <jmix:bindedComponent>
mixin type. This mixin defines a simple weakreference as a property.
[jmix:bindedComponent] mixin
- j:bindedComponent (weakreference)
This example definition defines that the tagging element has to be bound.
[jnt:tagging] > jnt:content, mix:title, jmix:siteComponent, jmix:bindedComponent
This example definition extends the calendar component, which needs to be bound to another component. This definitions adds the startDateProperty
and endDateProperty
properties which use choicelist initializers to retrieve the list of available properties from the bound component. If you bind your calendar to a list of news, content editors can access to all the news properties that populate the list, and they must choose a date property to make your calendar work as intended.
[jnt:calendar] > jnt:content, jmix:editorialContent, jmix:bindedComponent
- startDateProperty (string,choicelist[linkerProps=j:bindedComponent])
- endDateProperty (string,choicelist[linkerProps=j:bindedComponent])
In your module, view files should access the j:bindedComponent
property to retrieve the bound component.
<c:set var="boundComponent" value="${uiComponents:getBindedComponent(currentNode, renderContext, 'j:bindedComponent')}"/>
This example from the calendar module fills a map with the number of node per date.
<c:forEach items="${linked.node.nodes}" var="linkedChild" varStatus="status">
<fmt:formatDate pattern="yyyy-MM-dd" value="${linkedChild.properties[currentNode.properties.startDateProperty.string].date.time}" var="startDate"/>
<c:choose>
<c:when test="${empty datas[startDate]}">
<c:set target="${datas}" property="${startDate}" value="1"/>
</c:when>
<c:otherwise>
<c:set target="${datas}" property="${startDate}" value="${datas[startDate]+1}"/>
</c:otherwise>
</c:choose>
</c:forEach>
To enable a user to define to which component your component will be bound to, you have to define a draggable element in your view file. This draggable element can be dropped by the user to the element that they want bound to your component. To define this element just use the <<template:linker>>
tag.
Here is a simple example from calendar:
<template:linker path="*"/>
Here is a more advanced example of tagging that requires that you must have a specific mixin type on the bound component:
<template:linker path="*" mixinType="jmix:tagged"/>