More on content types

  Written by The Jahia Team
   Estimated reading time:

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 will be provided. It is possible to 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. Example : [option1, option2]

Default selectors for data types

  • for string, long, double, decimal, path, uri : will display an input text field on a single line
  • for boolean : will display a checkbox
  • for date : will display a date picker
  • for weakreference : will display 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.
    - 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

filepicker (weakreference, picker [ type = 'file' ])
imagepicker (weakreference, picker [ type = 'image' ])
folderpicker (weakreference, picker [ type = 'folder' ])
contentfolderpicker (weakreference, picker [ type = 'contentfolder' ])
editorialpicker (weakreference, picker [ type = 'editorial' ])
editoriallinkpicker (weakreference, picker [ type = 'editoriallink' ])
categorypicker (weakreference, picker [ type = 'category' ])
sitepicker (weakreference, picker [ type = 'site' ])
userpicker (weakreference, picker [ type = 'user' ])

Helpers

You may want to add description or helper text to your 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 this field using a resource bundle:

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

And this will result in displaying 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 disapear 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, sometime it make 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 exception are reference properties.

Note: Default values will only be used to prefill the editor when you are creating a 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

Restrict content type creation using permissions and roles

It's possible to only allow some conte type to be created by your users using permissions and roles.

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

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 using 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.