Skip to content

Components

Custom Components

A custom component is one you build for your own project, under apps/{project}/components/. Four pieces make it up: a definition resource (a .content.xml whose jcr:primaryType is kes:ComponentType), one or more views that render it, an optional dialog for the fields authors can edit, and, when the component needs logic, a Sling Model (a Java class that gives a component its server-side logic). A custom component does not require a datasource. Add one only when the component must display dynamically supplied content.

Component structure

Start a new component by adding a folder under the applications area of your project. The example below uses mysite as the project name (the Quick Start running example, groupId com.example) and sample-component as the component. The definition file sits at the component root, and the view and dialog live in child folders:

JCR structure
apps/mysite/components/sample-component/      # kes:ComponentType  (the .content.xml definition)
  common/
    content.html                        # default view (HTL)
  edit/
    .content.xml                        # edit dialog (kestros/cms2/dialog)

The content nodes (definition, view, and dialog) ship from the project’s application module as a FileVault content package. The Java Sling Model ships in the bundle produced by that same module.

Deliver docview content through a content package, not Sling-Initial-Content. The bundle content loader expects .json node definitions; docview .content.xml files loaded that way land as sling:Folder nodes and the kes:ComponentType is lost. Ship docview via the package (installPackage) and Java via the bundle (installBundle).

Definition resource

The definition is the component’s .content.xml at apps/mysite/components/sample-component/.content.xml. Its jcr:primaryType is kes:ComponentType, and it inherits from a parent component through sling:resourceSuperType:

sample-component/.content.xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
          xmlns:jcr="http://www.jcp.org/jcr/1.0"
          xmlns:kes="http://kestros.io/kes/1.0"
          jcr:primaryType="kes:ComponentType"
          sling:resourceSuperType="kestros/commons/components/kestros-parent"
          jcr:title="Sample Component"
          componentGroup="test Components"/>
Req: Y = required, Rec = recommended, blank = optional
PropertyTypeReqValue
jcr:primaryTypeStringYMust be kes:ComponentType
sling:resourceSuperTypeStringReckestros/commons/components/kestros-parent, or any other component you are extending from. Project components should extend a base; built-in base components omit this because they are the base.
jcr:titleStringRecName of the component
componentGroupStringRecThe group this component appears under in the authoring UI

Component view

Most components carry a common view: the default HTL script that renders it, at apps/mysite/components/sample-component/common/content.html. This is where you write the component’s markup. A view can pull in its Sling Model with data-sly-use and read properties from it (or read node properties directly with ${properties.name}). The Maven archetype scaffolds a placeholder common view for its generated sample component, which you then replace with your own markup:

sample-component/common/content.html
<sly data-sly-use.sampleComponent="${'com.example.mysite.application.components.SampleComponent'}" />
<p>${sampleComponent.sampleProperty}</p>
A component can carry more than one view (for example a framework- or brand-specific variant). See Component Views.

Sling Model

A Sling Model supplies the component’s logic. Kestros component models extend BaseComponent and are adaptable from a Resource. Set @Model’s resourceType to the component path so Sling can bind the model to the component automatically. See the Apache Sling Models documentation for the underlying annotations and injectors:

A component’s Sling Model lives in the project’s application module (package <group>.application.components), alongside the component it backs. Datasource models live in application too (package <group>.application.datasources): the application module holds every Sling Model that depends on the component libraries, so the core module stays free of them. See Project Structure for the full module layout.
SampleComponent.java
@KestrosModel()
@Model(adaptables = Resource.class,
        resourceType = "mysite/components/sample-component")
public class SampleComponent extends BaseComponent {

  // include methods here

}
@KestrosModel hooks the model into Kestros validation and in-CMS documentation (it can carry a validator and documentation paths). It is optional: the sample sites do not all use it, and a plain @Model works on its own.

Getters can be annotated with @KestrosProperty to document the JCR property, provide a default and a sample value, and mark it configurable in the edit dialog:

SampleComponent.java (getter)
@KestrosProperty(jcrPropertyName = "sampleProperty",
        defaultValue = "",
        description = "This is a sample property, which can be edited in the "
                + "component's edit dialog.",
        configurable = true,
        sampleValue = "Hello World!")
public String getSampleProperty() {
  return getProperty("sampleProperty", StringUtils.EMPTY);
}
BaseComponent is Resource-adaptable, so it cannot read the request or its query parameters. Request-scoped data comes from ComponentRequestContext (request-adaptable) in the view, or from a separate request-adaptable model. @KestrosProperty is recommended for documentation but is not required on every getter.

Edit dialog

A dialog lets authors edit the component’s properties. Add it at apps/mysite/components/sample-component/edit/.content.xml. Use the cms2 dialog shape: a root with sling:resourceType="kestros/cms2/dialog", a single <content> container (no tabs), then one node per field. Each field carries a name (the JCR property it writes) and a label, and picks its input type through sling:resourceType="kestros/cms2/fields/general/<type>":

sample-component/edit/.content.xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
          xmlns:jcr="http://www.jcp.org/jcr/1.0"
          xmlns:kes="http://kestros.io/kes/1.0"
          jcr:primaryType="nt:unstructured"
          sling:resourceType="kestros/cms2/dialog">
    <content jcr:primaryType="nt:unstructured">
        <text jcr:primaryType="nt:unstructured"
              sling:resourceType="kestros/cms2/fields/general/textfield"
              name="sampleProperty"
              label="Sample Property"
              focused="{Boolean}true"/>
    </content>
</jcr:root>
Do not use the legacy kestros/cms/dialog format. The older kestros/cms/dialog format used a different field vocabulary (fields addressed the property with propertyName= rather than name=). The cms2 shape shown above is the supported one for new components.

General fields are referenced as sling:resourceType="kestros/cms2/fields/general/<type>". A few common ones (see Dialogs for the complete list of 19):

Field typeresourceType suffixWhat it’s for
textfieldgeneral/textfieldSingle-line text input
selectfieldgeneral/selectfieldDropdown select from a list of options
richtextgeneral/richtextRich-text (formatted) editor
multifieldgeneral/multifieldRepeatable group of fields (a list of entries)

Kestros pickers are referenced as sling:resourceType="kestros/cms2/fields/kestros/<type>": component-picker, datasource-picker, layout-picker, theme-picker, and variations-picker.

For the full field reference and per-field configuration, see Dialogs. To feed a field or the component itself with dynamically supplied options, see Datasources.