Customizing Content Editor forms

November 14, 2023

You can customize the Content Editor interface with JSON overrides. This topic shows you how override sections, field sets, and fields.

Note: For examples of overrides, see Examples of content definition JSON overrides. For information on Content Editor interface elements and layout, see Understanding Content Editor forms and fields.

Form overrides

This section shows how to define static forms, how Jahia applies inheritance to sections, and provides an example of applying section overrides.

Defining static forms in Jahia modules

You can override the static definition of the forms by adding JSON files in the META-INF/jahia-content-editor-forms folder of your Jahia module, and then in the forms or fieldsets subdirectory. The files should have meaningful names and to ensure consistency between your definitions and your overrides. We recommend replacing the colon (:) between the namespace and the content type with an underscore. For example, the override of the qant:myFields  node type should be named qant_myFields.json.

Here's an example of a JSON static form definition:

{
  "nodeType": "qant:myFields",
  "priority": 1.0,
  "sections": [
    {
      "name": "layout",
      "hide": true
    }
  ]
}

With this definition, when you create or edit a node of the type  qant:myFields, a form without the section named layout displays. 

Other examples can be found in our Content Editor test folder.

Fieldsets overrides

In order to keep compatibility with previous versions, It is also possible to use field sets override, when the name of a fieldset is actually a node type name. Field set overrides are JSON files that are stored in the following directory:

/your_module/src/main/resources/META-INF/jahia-content-editor-forms/fieldsets

The JSON file has the following format:

{
 "name": "jmix:myType",
  "priority": 1.0,
   … fieldsets properties
}

However, doing this can lead to complex situations when fieldsets with the same name can appear in multiple sections (which is possible when fields of a same node type are “split” between different sections).
 

Checking proper registration of static forms

If you want to check if your form or field set definitions are properly deployed, check the Jahia logs for lines that look like this:

2022-12-12 15:43:48,490: INFO  [StaticDefinitionsRegistry] - Successfully loaded static fieldSets for name jmix:description from bundle://132.0:0/META-INF/jahia-content-editor-forms/fieldsets/jmix_description_move_section.json
2022-12-12 15:43:48,501: INFO  [StaticDefinitionsRegistry] - Successfully loaded static form for name jnt:category from bundle://138.0:0/META-INF/jahia-content-editor-forms/forms/jnt_category.json

Checking form generation

It can be helpful to know how to query a form generation to validate it is generated as expected. This can be done using the GraphQL API directly with the following query:

{
  forms {
    editForm(
      uiLocale: "en"
      locale: "en"
      uuidOrPath: "/sites/digitall/home/area-main"
    ) {
      sections {
        name
        displayName
        fieldSets {
          name
          displayName
          fields {
            name
            selectorType
            i18n
            readOnly
            multiple
            mandatory
            valueConstraints {
              displayValue
              value {
                type
                string
              }
              properties {
                name
                value
              }
            }
            defaultValues {
              type
              string
            }
          }
        }
      }
    }
  }
}

This will produce the JSON for the form for the specified node type, resulting from the merging of CND generation and all the associated static field set and form definitions.

How forms are inherited

You can use JSON overrides to redefine any property of the form. It’s possible to override only a single field inside a field set in a single section, without changing the other values.

Jahia gather all applicable forms on the current node - either coming from the CND, from a forms or from a fieldsets file. It takes the forms that can apply on the current primary node type, on the mixin that are added on the current node, and also on the dynamic mixin that can be added on the node.

All forms are sorted by priority and merged.

An override can add new sections / fieldsets / fields, but not remove them. In order to remove a section / fieldset / field , you should set the “hide” property. 

Simple form override example

This example shows how to perform section and preview overrides of the jnt:contentcontent definition and how to disable preview for the qant:myFieldsRequired content type.

With form overrides, you can define the sections and preview behavior for a nodetype such as jnt:content.

[qant:myFieldsRequired] > jnt:content, qamix:qaContent, jmix:editorialContent
  - sharedSmallText (string) mandatory
  - smallText (string) i18n mandatory

First, provide a JSON form definition for jnt:content that:

  • Displays sections content and metadata only
  • Sets preview to true

The JSON override (added to /your_module/src/main/resources/META-INF/jahia-content-editor-forms/forms/jnt_content.json) is:

{
 "nodeType": "jnt:content",
 "priority": 1.0,
 "hasPreview": true,
 "sections": [
    {
      "name": "classification",
      "hide": true
    },
    {
      "name": "layout",
      "hide": true
    },
    {
      "name": "options",
      "hide": true
    },
    {
      "name": "seo",
      "hide": true
    },
    {
      "name": "listOrdering",
      "hide": true
    },
    {
      "name": "visibility",
      "hide": true
    }
   ]
}

This creates a global rule and JSON override for jnt:content that is the default structure for all jnt:content and every node type that inherits from jnt:content.

But you would like to disable the preview for the qant:myFieldsRequired content type. You can override only hasPreview in a separate JSON override for qant:myFieldsRequired because, at the end, JSON overrides are merged together.

Here is the additional JSON override (added to /your_module/src/main/resources/META-INF/jahia-content-editor-forms/forms/qant_myFieldsRequired.json) to override qant:myFieldsRequired.

{
 "nodeType": "qant:myFieldsRequired",
 "priority": 2.0,
 "hasPreview": false
}

This way, only qant:myFieldsRequired will have preview disabled and all other jnt:content will have the preview enabled.

Label keys

You may have noticed the labelKey setting for a section. This values contains a resource bundle key that will be looked up based on the format of its value. If it doesn't contain the : character  it will be looked up in the current module (the one where the json file is). If not found, it will fallback on the Jahia global server resource bundle that should not be modified by user. This could however be useful to re-use system keys (such as in the above examples). If you want to specify your own keys in your own module, you must use the following syntax:

basename:key

where the basename will be the name of the resource bundle (the base name of the file that will be located in the src/main/resources/resources directory in the site template module) and the key will be the key inside the file. Here's an example:

mySiteTemplate:myLabel

will look for the myLabel key inside the src/main/resources/resources/mySiteTemplate_*.properties file in the site template module. If it cannot be found, it will try to look it up in the main Jahia system resource bundle.

Example of label overrides

{
  "nodeType": "cent:contentRetrievalCETest",
  "priority": 2.0,
  "sections": [
    {
      "name": "content",
      "fieldSets": [
        {
          "name": "<main>",
          "rank": "2.0",
          "fields": [
            {
              "rank": 5.0,
              "name": "jcr:title",
              "declaringNodeType": "mix:title",
              "labelKey": "content-editor-test-module:label.textoverride",
              "descriptionKey": "label.information"
            }
          ]
        }
      ]
    }
  ]
}

declaringNodeType

You need to use declaringNodeType when the field you are declaring is not declared on the primary nodetype.

Field set properties

The following properties define a field set:

  • name (string): 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). Note that the same field set name can be used in different sections
  • label / labelKey (string): label or resource bundle key
  • description / descriptionKey (string): description or resource bundle key
  • requiredPermission: permission required to see the fieldset
  • rank (decimal): position of the field set in the form. The default value is 0.0
  • hide (boolean): If false, the field set is part of the generated form, but is not displayed
  • readOnly (boolean): cannot add/remove associated dynamic mixin, if this field set is a dynamic mixin
  • fields (array): Array of fields that compose the field set

Field overrides

The section describes field overrides, lists field properties that you can override, and provides examples of field overrides.

Field override basics

JSON overrides can override existing fields or add new fields. You can define field overrides in the fields section of field set override. The override applies to the node type defined by the name property of the field set.

{
  "sections": [
    {
      "name": "section",
      "fieldSets": [
        {
          "name": "jmix:myType",
          "fields": [
            {
              "name": "fieldName",
              "mandatory": false,
              ...
            }
          ]
        }
      ]
    },

Field properties

Here the properties that can be overridden or used to create a field:

  • name: name of the field. To override an existing property, it must match the property name. Mandatory. Field name is unique in the whole form

  • label / labelKey: label or key to resource bundle for the section 

  • description / descriptionKey: label or key to resource bundle for the section 

  • errorMessage / errorMessageKey: label or key to resource bundle for the errorMessage 

  • hide: do not display the field 

  • rank: position of the field in the fields 

  • requiredType: field type

  • selectorType: Defines the selector type (input) use for the field.

  • i18n: is field internationalized

  • readOnly: If true the field is set as read only.

  • multiple: is field multiple

  • mandatory: If true the field is marked as mandatory.

  • valueConstraints: Array of constraints applied on the field.

  • defaultValues: Array of default values.

Known limitations

  • The properties multiple and I18n can not be overridden by JSON definition. As the definition does not allow to have multiple values or internationalized values, there will be an error when you will try to save the data in the JCR.

Moving fields

Field can be moved by adding it into another section / fields set. Rank will define where the field will appear compared to others.

A field will always appear at most once in a form - the form override that declare a field, which have the highest priority, will define where the field will appear.

The following will move the jcr:title field in a field set and the system name in another field set, for all nodes of type jnt:page
 

{
  "nodeType": "jnt:page",
  "priority": 4.0,
  "sections": [
    {
      "name": "content",
      "fieldSets": [
        {
          "name": "title-field-set",
          "label": "Title here",
          "rank": 0.0,
          "fields": [
            {
              "name": "jcr:title"
            }
          ]
        },
        {
          "name": "new-field-set-2",
          "rank": 0.1,
          "fields": [
            {
              "name": "ce:systemName"
            }
          ]
        }
      ]
    }, {
      "name": "metadata",
      "fieldSets": [
        {
          "name": "name-field-set",
          "label": "System name here",
          "rank": 0.0,
          "fields": [
            {
              "name": "ce:systemName"
            }
          ]
        }
      ]
    }
  ]
}

Displaying a hidden property

Hidden properties are not displayed by default. However, this behavior can be overridden by using:
"hide": false

Note: If the property is not declared on the primary nodetype, nor inherited, then you need to use declaringNodeType as well, to specify which node type provides the property. E.g.:
              "name": "j:invalidLanguages",
              "declaringNodeType": "jmix:i18n"
              "hide": false