Enhancing content types for editors

November 14, 2023

In this topic, you will learn more about content types definitions. As a Jahia developer, you'll be able to use several options in the content properties that you define, to improve the experience of end users in Content Editor:

  • Defining a helper for your property
  • Setting custom validations and related custom messages
  • Adding constraints for dates
  • Setting a property as mandatory
  • Adding a default value for your property
  • Initializing choicelists (dropdown fields) with the right values
  • Specifying manual or automatic ordering for subcontent in a content list

 Before diving into these options, you'll need to understand the selectors that are available for your properties. 

Selectors

Depending on the property type, a corresponding input field is provided. You can override the default input field by adding a specifier after the type definition.

Usage/syntax

- field-name (type)
- field-name (type,selector)
- field-name (type,selector[options])

where

  • type
    is one of string, long, double, decimal, path, uri, boolean, date, binary, weakreference
  • selector
    is one of text, richtext, textarea, choicelist, datetimepicker, datepicker, picker, category, checkbox
  • options
  • are relative to the selector, you can chain them using a coma as separator. For example, [option1, option2].

Default selectors for data types

  • for string, long, double, decimal, path, uri: displays an input text field on a single line
  • for boolean: displays a checkbox
  • for date: displays a date picker
  • for weakreference: displays a selector

Custom selectors

You can change the default display of a screen

  • text : will display a single line form
  • richtext : will display ckeditor
  • textarea : will display a multiline area
  • choicelist : will display a drop down list with values define by the default value set or options. The choiceLists initializers defined by default are : resourceBundle, country, templates, templatesNode, users, nodetypes, subnodetypes, nodes, menus, script, flag, sortableFieldnames, moduleImage, linkerProps, workflow, workflowTypes, sort and componenttypes. Note that choicelist does not support decimal values.
    - firstField (string, choicelist[sortableFieldnames]) < 'true', 'false'
    - play (string, choicelist[resourceBundle]) < 'true', 'false'
    - templateForLink (string, choicelist[templates,resourceBundle])
    - nodeType (string, choicelist[subnodetypes = 'jnt:page,jnt:contentList,jnt:folder',resourceBundle])
  • datetimepicker : will display a single line field and a calendar to select date and time
  • datepicker : will display a single line field and a calendar to select date
  • picker : will display a picker, depending of the option. The picker types defined by default are : file, image, folder, contentfolder, portlet, page, editorial, editoriallink, category, site, user and usergroup
    - source (weakreference, picker[type='file'])
    - image (weakreference, picker[type='image'])
    - j:node (weakreference, picker[type='contentfolder'])
  • category : will display a category picker
  • checkbox : will display a checkbox

Available pickers

The following pickers are available:

Picker name Description Selectable types*
Default picker
(default)
The default picker is used to browse pages, content folders and files. As most of the content types can be selected, it is best to define content type restrictions not to provide an overwhelming experience to the editors.
Available with Content Editor 4.1.0
  • jnt:content
  • jnt:file
  • jnt:page
  • jmix:navMenuItem
Editorial picker
(editorial)
 
This is the picker to use when referencing editorial content (e.g. a news or a rich text). Pages and content folders can be browsed.
  • jnt:page
  • jnt:contentList
  • jnt:contentFolder
  • jmix:siteContent
  • jmix:editorialContent
Droppable content picker
(droppableContent)
 

This is the picker to use when referencing droppable content. Pages and content folders can be browsed.
An overlap is possible with the Editorial picker, as many default droppable content  types are also editorial contents.
Available with Content Editor 4.1.0

 

  • jmix:droppableContent
File picker
(file)
Picker used to browse the media folders to select files.
  • jnt:file
Image picker
(image)
Picker used to browse the media folders to select images.
  • jmix:image
Video picker (video) Picker used to browse the media folders to select video files.
Available with Content Editor 4.1.0
  • jnt:file with video mime type
PDF picker (pdf) Picker used to browse the media folders to select pdf files.
Available with Content Editor 4.1.0
  • jnt:file with pdf mime type
Page picker
(page)
Picker displaying the page tree to only allow the selection of pages, e.g. when building links.
If you rely on jmix:mainResource to display some content in a full page view, then you need to use the Editorial link picker below.
  • jnt:page
Editorial link picker
(editoriallink)
This picker is pretty similar to the page picker, as its main purpose is to select pages or content displayable in a full page view (jmix:mainResource).
As such content can be created under pages or in content folders, it’s possible to browse both the page tree and the content folders.
  • jnt:page
  • jmix:mainResource
Media folder picker
(folder)
This picker is used to browse and select media folders (folders containing files)
  • jnt:folder
Content folder picker
(contentfolder)
This picker is used to browse and select content folders (folders containing editorial content)
  • jnt:contentFolder
Category picker
(category)
This picker is used to browse and select content folders.
This is different from the category selector, used by default to assign categories to contents.
  • jnt:category
User picker
(user)
This picker is used to search and select users
  • jnt:user
User group picker
(usergroup)
This picker is used to search and select user groups
  • jnt:group
Site picker
(site)
This picker is used to search and select sites.
Note that if you need to select a site, we advise to use the following statement in the definition in order to display a more convenient drop down listing the sites instead of displaying a picker in a modal:
- site (weakreference,choicelist[nodes='/sites;jnt:virtualsite']) nofulltext

 

  • jnt:virtualsite

* if type restrictions are set for the property in the definition file, then these types take precedence over the selectable types provided by the picker, so the user can only select types allowed by the definition. See Setting content type restrictions

If none of these pickers meet your needs, you can override them for a given content property or define your own picker. Find out more in the Customizing Content Editor pickers page.

Helpers

You may want to add description or helper text to either your content fieldset or a given field, to give some additional information to the user, for example here is a Job offer content, that contains a "skills" property. We expect the contributor to fill this multiple field with the required skills for the job.

The definition looks like this:

[qant:jobOffer] > jnt:content, qamix:qaContent, jmix:editorialContent
 - skills (string, text) i18n multiple

And the generated form looks like this:

Content-Editor-helper-2.png

It's possible to add a custom internationalized helper for the skills field using a resource bundle:

qant_jobOffer.skills = Required skills
qant_jobOffer.skills.ui.tooltip = List the required skills for this job offer

Since 8.0.3, it's also possible to add a custom internationalized helper for the jobOffer fieldset using a resource bundle:

qant_jobOffer_description = Customize job offer attributes

This displays the tooltip message for this field:

Content-Editor-helper-3.png

Regular expressions validation and custom error messages

If you need to control and validate that a text field for a given property has a specific format you can use regexp constraint.

[qant:jobOffer] > jnt:content, qamix:qaContent, jmix:editorialContent
 - skills (string, text) i18n multiple
 - contactMail (string, text) mandatory < '^$|[A-Za-z0-9._%+-]+@(?:[A-Za-z0-9-]+\\.)+[A-Za-z]{2,}'

In the previous definition we created the new property "contactMail" with a regexp constraint.

By default the form will show this error message in case the text field is invalid:

regexp-valdiation-error.png

But you can customize this message using the resource bundle:

qant_jobOffer.contactMail = Contact mail
qant_jobOffer.contactMail.constraint.error.message = Please provide a valid email

This will display your internationalized message as a warning:

regexp-validation-custom.png

And the warning message will automatically disappear as soon as the text field value will match the regexp.

Date property constraints

It's possible to bound the date value using date boundary constraints in your definitions.

Samples are better than explainations, you can see in this definition all type of date boundary constraints:

[qant:dateConstraint] > jnt:content, qamix:qaContent, jmix:editorialContent
   - dateConstraintLowerBoudaries (date, DatePicker) < "(2019-06-04T00:00:00.000,)"
   - dateConstraintUpperBoudaries (date, DatePicker) < "(,2021-06-20T00:00:00.000)"
   - dateConstraintBothBoudaries (date, DatePicker) < "(2019-06-04T00:00:00.000,2021-06-20T00:00:00.000)"
   - dateConstraintLowerBoudariesInc (date, DatePicker) < '[2019-06-04T00:00:00.000,]'
   - dateConstraintUpperBoudariesInc (date, DatePicker) < '[,2021-06-20T00:00:00.000]'
   - dateConstraintBothBoudariesInc (date, DatePicker) < '[2019-06-04T00:00:00.000,2021-06-20T00:00:00.000]'
   - datetimeConstraintLowerBoudaries (date, DateTimePicker) < '(2019-06-04T05:00:00.000,)'
   - datetimeConstraintUpperBoudaries (date, DateTimePicker) < '(,2021-06-20T05:10:00.000)'
   - datetimeConstraintBothBoudaries (date, DateTimePicker) < '(2019-06-04T05:10:00.000,2021-06-20T05:10:00.000)'
   - datetimeConstraintLowerBoudariesInc (date, DateTimePicker) < '[2019-06-04T05:00:00.000,]'
   - datetimeConstraintUpperBoudariesInc (date, DateTimePicker) < '[,2021-06-20T05:10:00.000]'
   - datetimeConstraintBothBoudariesInc (date, DateTimePicker) < '[2019-06-04T05:10:00.000,2021-06-20T05:10:00.000]'
  • You can delimit your date value using a minimal boundary (always the first one) or maximal boundary (always the second one) or both 
  • The boundaries always need to be separated by a comma, even if you only use one of them.
  • You can specify if the boundary is included using [brackets] or if the boundary is excluded by using (parentheses)
  • You can use these constraints on both DatePicker and DateTimePicker

If you decide to use these boundaries, the date picker will only allow the user to select a valid date:

date-picker-1.png

If the user enters a not allowed date, then a validation warning will be displayed automatically:

date-picker-2.png

Mandatory properties

It's possible to set some properties mandatory, sometimes it makes sense to force your contributor to fill mandatory properties.

To do this you can add the keyword "mandatory" in your definition.

[qant:allFieldsRequired] > jnt:content, qamix:qaContent, jmix:editorialContent
   - sharedSmallText (string) mandatory
   - smallText (string) i18n mandatory
   - sharedTextarea (string, textarea) mandatory
   - textarea (string, textarea) i18n mandatory
   - sharedChoicelist (string, choicelist[resourceBundle]) = 'choice1' mandatory < 'choice1', 'choice2', 'choice3'
   - choicelist (string, choicelist[resourceBundle]) = 'choice1' i18n mandatory < 'choice1', 'choice2', 'choice3'
   - sharedLong (long) mandatory

Every kind of property can be mandatory, even multiple value properties. They will be displayed like this in the editor:

mandatory-prop-1.png

And the contributor will not be able to save until he provide a value for this mandatory properties:

mandatory-prop-2.png

Default values

It's possible to provide default values for your properties, if you do so it will prefill the editor with your configured default values.

Almost every type of property can have default values, even multiple values, the only exceptions are reference properties.

Note: Default values will only be used to prefill the editor when you are creating new content, but not when you are editing existing content.

Default values for single value properties

[qant:AllFieldsDefault] > jnt:content, qamix:qaContent, jmix:editorialContent, jmix:defaultPropMixin
    - sharedSmallText (string) = 'value 1'
    - sharedTextarea (string, textarea) = 'value 1'
    - sharedChoicelist (string, choicelist[resourceBundle]) = 'choice1' < 'choice1', 'choice2', 'choice3'
    - sharedLong (long) = 1
    - sharedDouble (double) = 1.1
    - sharedBoolean (boolean) = true
    - sharedBigtext (string, richtext) = 'value 1'
    - sharedDate (date) = '2019-06-04T00:00:00.000'
    - sharedDecimal (decimal) = 1234567890.123456789

Will display:

default-values-1.png

Default values for multiple value properties

[qant:allFieldsMultipleDefault] > jnt:content, qamix:qaContent, jmix:editorialContent
   - sharedChoicelist (string, choicelist[resourceBundle]) = 'choice1' multiple < 'choice1', 'choice2', 'choice3'
   - dynamicChoicelist (string, tag[autocomplete=10,separator=',']) = 'tag1', 'tag2' facetable nofulltext multiple
   - sharedSmallText (string) = 'test1=1', 'test2=2' multiple < '[a-zA-z1-9]*=[a-zA-z1-9]*'
   - sharedTextarea (string, textarea) = 'value1', 'value2' multiple
   - sharedLong (long) = 1, 2 multiple
   - sharedDouble (double) = 1.1, 2.2 multiple
   - sharedBoolean (boolean) = true, false multiple
   - sharedBigtext (string, richtext) = 'value 1', 'value 2' multiple
   - sharedDate (date) = '2019-06-04T00:00:00.000', '2029-06-04T00:00:00.000' multiple
   - sharedDecimal (decimal) = 1234567890.123456789, 1134567890.113456789 multiple

Will display:

default-values-2.png

Restricting content type creation with permissions and roles

You can use permissions and roles to restrict the content types that your users can create. Inside the Jahia Administration in the role administration page, you can select or unselect the node types sections you want to allow for a given role.

These permissions are available on "Current site" and "Templates and Components":

component-permissions.png

Every permission listed here corresponds to a mixin and section used to display the content type in the content type tree selector.

for example:

[qant:jobOffer] > jnt:content, jmix:basicContent, jmix:editorialContent
 - skills (string, text) i18n multiple
 - contactMail (string, text) mandatory < '^$|[A-Za-z0-9._%+-]+@(?:[A-Za-z0-9-]+\\.)+[A-Za-z]{2,}'

Is displayed under basic content section, because of the mixin inheritance on "jmix:basicContent":

tree-selector-content-type.png

If you disable the permission "Component jmix basic content" for role "editor",

any user using the role "editor" on the current site will not be able to create any content of the "jmix:basicContent" section, including our jobOffer content type.

Choicelists

It's possible to provide a data set for a choicelist in multiple ways. 

You can provide the available values directly in the definition:

[qant:choicelist] > jnt:content, qamix:qaContent, jmix:editorialContent
 - resourceBundle (string, choicelist[resourceBundle]) = 'choice1' < 'choice1', 'choice2', 'choice3'

Then you can provide a translation for each value using the resourceBundle option, and provide the internationalized name using resource bundle files:

qant_choicelist.resourceBundle = Resource bundle
qant_choicelist.resourceBundle.choice1 = Choice one
qant_choicelist.resourceBundle.choice2 = Choice two
qant_choicelist.resourceBundle.choice3 = Choice three

This will display:

choicelist-1.png

Alternative selector for multiple selection in a choicelist

Available with Content Editor 4.2

The default drop down for choicelists supports multiple selection. However, when the list is too long or when one needs to manage the order of the selected items, it is advised to use the alternative MultipleLeftRightSelector 

A json override is needed to use this selector.

MultipleLeftRightSelector.png

Choicelist initializers

You can use choicelist initalizers to provide dynamic data sets, Jahia provides some of them ready to be reused.

The user choicelist

[qant:choicelist] > jnt:content, qamix:qaContent, jmix:editorialContent
 - users (string, choicelist[users])

Will display the list of users available on the server:

choicelist-2.png

The country choicelist

[qant:choicelist] > jnt:content, qamix:qaContent, jmix:editorialContent
 - country (string, choicelist[country])

Will display a list of countries:

choicelist-3.png

The node type choicelist

[qant:choicelist] > jnt:content, qamix:qaContent, jmix:editorialContent
    - j:nodeTypes (string,choicelist[nodetypes=nt:base])

Will display a list of all available nodetypes that inherit from the nodetypes option:

choicelist-4.png

The node choicelist

[qant:choicelist] > jnt:content, qamix:qaContent, jmix:editorialContent
 - category (weakreference, choicelist[nodes='/sites/systemsite/categories/;jnt:category'])

This one is a little bit complex, but very useful, you can provide a path and a node type and it will list the available nodes that correspond, you will be able to store the result in a weakreference directly.

In the current example, it's a way to list some categories and store the chosen one in a property named "category":

choicelist-5.png

Note: this can be useful, because you can setup the contents you want to display in the list, by choosing the path and the node type.

In case you want to categorize your content, you just have to enable the fieldset already available in the editor:

 

category-1.png

Then select the categories you want to add to your content.

category-2.png

More About choicelists

Choicelist initializers can be extended, and you can create your own ones, if you want to know more about choicelist initializers, please read: 

Choicelist initializers documentation

Setting manual and automatic ordering of subcontent

In certain cases, editors can order the subcontent (children) in a content list. Content Editor provides two options for ordering:

  • Manual ordering
    Allows editors to manually drag-and-drop subcontent and reorder them as they like.
    manualOrder.png
  • Automatic ordering
    Allows editors to automatically order subcontent by selecting one or more shared child properties and specifying the sort direction.
    automaticOrder.png

There are multiple ways to specify how ordering occurs, which are located in your content definitions.

Note: By default, these features are already available on jnt:contentList and jnt:area.

Sometimes you may want your content list to be only manually orderable or only automatically orderable, or you may want both options and let the editor choose.

To specify how your content list is ordered:

  1. To make your content list only manually orderable, specify the orderable keyword on your content list definition, like this:
    [qant:simpleListManuallyOrderable] > jnt:content, jmix:list orderable
     + * (jnt:text)
    Your editors will only be able to manually order the text subcontent of this list and will not be able to automatically order them.
  2. To make your content list only automatically orderable, add the jmix:automaticallyOrderable mixin to your content list, like this:
    [qant:simpleListAutomaticallyOrderable] > jnt:content, jmix:list, jmix:automaticallyOrderable
     + * (jnt:text)
  3. To have both options and let the editor choose, combine the orderable keyword and jmix:automaticallyOrderable mixin, like this:
    [qant:simpleListHybridOrderable] > jnt:content, jmix:list, jmix:automaticallyOrderable orderable
     + * (jnt:text)

Automatic ordering details

Jahia applies automatic ordering to subcontent during the rendering of a list when a user loads a page. Ordering is done by the list.hidden.header.jsp JSP view of jmix:list. Note that subcontent is not reordered in the JCR storage and is only ordered when the page displays. This means that automatic ordering is not applied if content is consumed through our GraphQL API. To ensure that the content is always ordered when using Jahia in headless, you must use sorting capabilities of our API and queries.

To make the automatic ordering work, you have to inherit from jmix:list and ensure the view is used to load and display the subcontent. For developers, here is the source: list.hidden.header.jsp.

Manual ordering details

Not all the node types are visible in the manual ordering section. By default, Jahia displays the subcontents of jnt:content  types only.

Most of the time, your content inherits from jnt:content. If your content does not inherit from jnt:content and you want to display your child nodes in the manual ordering section, you can set the jmix:manuallyOrderable mixin on the child node type definition. This way it will appear in the manual ordering section.

The following example shows a definition for this use case.

[qant:simpleListManuallyOrderable] > jnt:content, jmix:list orderable
 + * (qant:simpleChild)

[qant:simpleChild] > jmix:manuallyOrderable
 + childProp (string)
Remember, the jmix:manuallyOrderable mixin is only meant to be used on child node types and not on the list itself.

Compatibility between Jahia 7 and Jahia 8

Examples for the children ordering section in Content Editor show Jahia 8 because some mixins have been introduced in Jahia 8 to simplify how you handle children ordering.

We have tried at the same time to keep the compatibility with the same kind of features that were already available in Jahia 7. If you come from Jahia 7 or another previous version, feel free to continue to use the mixins you already know that provide similar features. Here is a summary table of all available mixins (old and new) and options for the child ordering feature:

Name of the mixin Level v7/v8 description
orderable
(not really a mixin)
List Different In v7, used to display the List Ordering tab that contained both the manual and automatic list ordering features.
In v8, used to display the UI to manually order subcontent.
jmix:list List Same Used to identify content that can be displayed as a list.
Used by the views of list (hidden.load.jsp and hidden.header.jsp) to style the list and load contents.
jmix:automaticallyOrderableList List New

In v8, displays the UI for automatic list ordering (allowing you to add jmix:orderedList on any content type and not just on jnt:contentList/jnt:areas).
This mixin wasn’t added to all content types that inherit from the jmix:list because some content types, like query components, require the jmix:list mixin and don’t support automatic ordering.

jmix:renderableList List Same Used to set a view for the subcontent of the list (to avoid defining it on each subcontent item).
jmix:manuallyOrderable Subcontent Same

Subcontents of jnt:content and jmix:manuallyOrderable types display in the list of subcontents in the manual ordering.
Note that you should not add this to the list or parent content.

jmix:orderedList List Same Used to add the properties to store the automatic list ordering criteria when a user selects Automatic list ordering in the UI.
This mixin is used internally by Jahia and you should not add it to your content definition.
jmix:listOrdered List Same Mixin associated with the ordered/unordered view that is added on lists and areas.
If you use this mixin, note that it may become deprecated in a future release.