How Content Editor forms are generated

November 14, 2023

The Content Editor module generates forms for content editing from a JSON definition. This JSON definition is built from the node type definition (definitions.cnd) and from the JSON files in the META-INF/jahia-content-editor-forms folder.

The following diagram shows an example of how forms are generated for a custom module that is used to edit an event. The form is built from the definitions.cnd file for Acme:event and the jmix_title.json and acme_event.json overrides. The FormService contains logic that merges the definitions.cnd file and the overrides. Finally, the Content Editor form is rendered for Jahia content editors through the Jahia GraphQL API.

content-editor-form-schema.png

The FormService merges the definition.cnd file and JSON override files in the following way:

  • If a CND definition exists in the JCR, it is used to generate a form definition dynamically.
  • If Jahia modules define static forms that either override or define new forms, they will be merged in order of priority with first the dynamically generated forms from the JCR definition (if it exists) and then with the static JSON form definitions that have a higher priority.
  • If the node type has both CND definition and JSON form definitions, they will be merged, to get the final JSON form definition to generate the form.

This example shows the JSON form definition for the jnt:news node type.

"data":{
  "forms":{
    "createForm":{
      "name":"jnt:news",
      "displayName":"News entry",
      "description":"",
      "sections":[{
        "name":"content",
        "displayName":"Content",
        "description":null,
        "fieldSets":[{
          "name":"jnt:news",
          "displayName":"News entry",
          "description":"",
          "dynamic":false,
          "activated":true,
          "fields":[{
            "name":"jcr:title",
            "displayName":"News Title",
            "description":"This is your news title<br/>It will be displayed as the header of your news.",
            "errorMessage":"",
            "mandatory":true,
            "i18n":true,
            ...},
          ...],
        ...},...]
      },...]
    }
  }
}

Understanding the form structure

The form files located in META-INF/jahia-content-editor-forms/forms have the following structure:

  • nodeType: The name of the node type on which this form will be applied. For example, jnt:news.
    It can be any node type, primary or mixin. The override will apply if the node type matches.
  • orderable: this form will only be applied if nodetype has orderable children
  • priority: Specifies the override order. A higher number indicates a higher priority. For example, a JSON override with priority set to 2.0 will overwrite one with a priority set to 1.0. 
  • hasPreview: display or not the preview
  • a list of sections
    A section definition contains a:
    • name: name/identifier of the section
    • label / labelKey: label or resource bundle key for the section's label
    • description / descriptionKey : description or resource bundle key for the section's description
    • rank: position of the section (if no rank specified and ranks are equals, sections will be ordered alphabetically)
    • requiredPermission: permission required to see the section
    • hide: do not display the section
    • displayModes: if the section should be displayed in some modes only (edit or create)
    • expanded: expanded by default or not
    • fieldSets: list of fieldSets
{
  "name": ...,
  "priority": ...,
  "sections": [
    {
      ...
    }
  ]
}

A form is split between “sections” (which are mapped to “itemType” in CND), and “fieldsets” (which are created for every mixin type).

Understanding the field set structure

When using static declaration of field sets, you can override existing properties declared in the definitions.cnd file. However, you cannot use overrides to create a new field that is not declared in a JCR definition as this behaviour isn't supported by the product.

A field set is composed of a:

  • name : name of the field set (can be a node type or not - use <main> for using the main fieldset, i.e. primary node type name)
  • label / labelKey : label or resource bundle key for the field set 
  • description / descriptionKey : description or resource bundle key
  • rank : position of the field set
  • hide : do not display the field set
  • readOnly : cannot add/remove associated dynamic mixin, if this field set is a dynamic mixin
  • fields : list of fields

Fields are defined with :

  • name: name of the field
  • label / labelKey: label or resource bundle key
  • description / descriptionKey: description or resource bundle key
  • errorMessage / errorMessageKey: errorMessage or resource bundle key
  • hide: do not display the field set 
  • rank: position of the field in the fields set
  • requiredType: field type
  • selectorType, selectorOptionsMap: selector to use and associated options
  • i18n: is field internationalized
  • readOnly: is field read only
  • multiple: is field multiple
  • mandatory: is field mandatory

The following example shows the structure of definitions files.

{
  "name": ...,
  "rank": ...,
  "priority": ...,
  "dynamic": ...,
  "removed": ...,
  "activated": ...,
  "fields": [
    {
      "name": ...,
      "description": ...,
      "requiredType":...,
      "selectorType": ...,
      "i18n": ...,
      "readOnly": ...,
      "multiple": ...,
      "mandatory": ...,
      "target": {
        "sectionName":...,
        "rank": ...
      }
    }
  ]
}

What's next

Now that you understand the Content Editor form structure and how forms are generated, you can learn how to customize Content Editor at Customizing Content Editor forms or go straight to the Examples of content definition JSON overrides. If you need background on Content Editor interface elements and layout, see Understanding Content Editor forms and fields.