Input types
Contents
The content types we’ve created previously in this guide have only used two basic input types: TextLine and TextArea. However, Content Studio has a lot more up its sleeve than that! Input types dictate what kind of data the user can or must add any piece of content. This chapter introduces more new types of inputs and explains how you can configure them to your liking.
If you’re used to working with HTML, be aware that XP’s input elements are not the same as HTML input elements. |
The tasks and examples in this chapter are based on work done in previous chapters (starting with the sandboxes chapter). If you want to follow along with the examples, make sure you’re all caught up. |
Configuration
All input types share a number of options that affect how they act. These options are:
-
label
(required) -
What the input should be labeled as in the content form.
-
occurrences
(optional) -
Specifies the minimum and maximum instances of this field. Defaults to "one optional".
-
default
(optional) -
Gives a default value to the input.
-
help-text
(optional) -
Lets you specify a description of the input field to show to the user.
-
config
(optional) -
Input type-specific configuration.
The
config
element is for input-specific configuration. Because the input types are so different to each other, they all support different options. Theconfig
element allows us to use regex validation for TextLine inputs, configure formatting options for HtmlAreas, and to dictate what numeric values a Long or a Double input accepts.
All of the shared configuration options (label
, occurrences
, etc.) are described in more detail in the input types schema documentation. Additionally, all input types and their respective config
options are listed in the the input types documentation.
To show an example of the configuration options work, let’s examine some TextLine inputs with different configurations.
<input type="TextLine" name="textlineRequired">
<label>Required input with default</label> (1)
<help-text>This text should provide additional information to the user.</help-text> (2)
<occurrences minimum="1" maximum="1" /> (3)
<default>This is a required input with a default value.</default> (4)
</input>
<input type="TextLine" name="textlineOptional">
<label>Optional input</label>
<occurrences minimum="0" maximum="1" /> (5)
</input>
<input type="TextLine" name="textlineList">
<label>Input list</label>
<help-text>This input can have as many values as you want.</help-text>
<occurrences minimum="0" maximum="0" /> (6)
</input>
1 | The label is shown above the input and provides context to the user. |
2 | The help-text can provide extra context and information to the user. It’s hidden by default, but can be shown by activating the help text button. |
3 | This instance of the occurrences element specifies that this is a required input. It must have at least one and at most one value. |
4 | The default value gets added to the input by default. The user can manually override this. |
5 | When you specify minimum="0" and maximum="1" on an occurrences element, that makes the input optional. This is the default. |
6 | When you set maximum="0" on an occurrences element, the user can add as many values as they want to. |
This set of inputs would be rendered as in the following picture. As specified in the above configuration, notice:
-
The required input field has a red asterisk to signify that it must be filled out.
-
The required input field already has a value provided via the
default
configuration option. -
The help texts for the required input field and for the input list are both visible
-
The input list has controls to add more inputs and remove existing inputs

Occurrences
The occurrences configuration option decides how XP treats the input value. Use occurrences to indicate whether an input is expected to be a list or a single element and whether the input is required or not. The occurrences element has two required attributes, minimum
and maximum
. Use these to control the number of instances the user can create.
The minimum
attribute specifies that the user must fill out at least this many instances of the field. Usually it is set to 0
or 1
. A zero indicates that the field is optional and that the user does not need to fill it out. A one means the field is required.
The maximum
attribute tells XP how many instances the input field can have at most. 0
is a special value here, indicating that the user can have as many as they want (in other words: there is no maximum).
A couple of common configuration tricks:
-
If you don’t add an
occurrences
element, XP uses the default, which isminimum="0"
,maximum="1"
, meaning that the input is optional. -
To make the input required, set both
minimum
andmaximum
to1
. -
To create a list of inputs, set
maximum
to0
(if there is no limit to how many items the user can add) or to the desired maximum.
If maximum is greater than 0 , make sure that minimum is less than or equal to maximum . Otherwise, the input will never be considered valid according to XP. |
Common inputs
Apart from the input types we’ve already gotten familiar with, XP also has input types created for other kinds of data. You can always find the full list over at the input types reference docs, but some useful and common ones are:
- ComboBox
-
A dropdown menu containing predefined options for the user to select from. Allows selection of one or more options.
Figure 2. The ComboBox input type - Date and DateTime
-
Provides an interactive date picker (with a time component in DateTime’s case) to save date and times.
Figure 3. The DateTime input type - GeoPoint
-
Stores GPS coordinates.
Figure 4. The GeoPoint input type - HtmlArea
-
Provides a rich text, multi-line input. We’ll discuss this in detail in the next chapter.
Figure 5. The HtmlArea input type
Additionally, XP has more complex input types, which we’ll look at next.
ImageSelector

Images are a key part of many web experiences: they add color, break up the content, and gives the reader something to rest their eyes on. XP’s image selector allows you to select an image for a piece of content and also to upload new images.
<input name="myimage" type="ImageSelector">
<label>My Image</label>
</input>
Read more about the configuration of image selectors in the reference docs.
After you’ve added an image (or several), you can highlight it and click the edit button. This will take you to the image editing form. This is the same form as we saw in the previous chapter.

ContentSelector

The image selector we just saw is actually a specialized form of the more complex ContentSelector input type. The ContentSelector input type allows you to reference other content. Let’s say you have two content types: one of type person and one of type food. If you want to be able to specify which dishes the person likes, you could use a content type to create a reference from the person to their favored dish.
Because referencing other content types comes with a lot of variability, the ContentSelector type has configuration options to support this. You can choose to allow only certain content types or only content that’s available at a certain path. You can also change whether the selector should show content in a tree-style hierarchy or as a flat list of content.
The full list of ContentSelector configuration options is available in the reference docs, including a number of examples to explain content inclusion and exclusion. However, a simple configuration could look like this:
<input name="mycontentselector" type="ContentSelector">
<label>My ContentSelector</label>
<config>
<allowContentType>citation</allowContentType>
</config>
</input>
Task: artists and animals
Time for a little recap! We’ll put together everything we’ve learned about content types and input types thus far to create a new data set. A solution is listed below, but try and see if you can solve it yourself first. If you’re wondering how to achieve some of the goals, try consulting the documentation that’s been linked to in this chapter.
Your task is to create a new content type: Animal
and to update the Artist
content type with new constraints and fields. By the end of this chapter, you should have content types that look like this in Content Studio:

Animal constraints:
-
Make the display name use "species" as its label. Hint: check out the content type form definition and look for something that allows you to do this.
-
An animal can also have alternative names for its species (for instance, the reindeer is also known as caribou). Allow the user to add as many alternative names as they want.
-
An image selector that accepts between 0 and 3 images.
-
Help text where you think it would be helpful.
When you’ve created the content type, create a new folder in Content Studio at next to the artists folder. Call it "animals".
For the artist content type, here’s what’s going to change:
-
Add a ContentSelector input that allows only content of the "Animal" type and that must be nested under the site’s "animals" folder. Call it
favoriteAnimal
.
To verify that everything works, create some animals, and try creating a content link between a artist and an animal.
When you’ve got that, create a GraphQL query that’ll fetch all artists and list what their favorite animals are, as well their animals' descriptions .
Solution
-
Create the animal content type. In
src/main/resources/site/content-types/animal/animal.xml
, place the following content:The animal content type<content-type> <display-name>Animal</display-name> <description>An animal that lives on planet Earth</description> <display-name-label>Species</display-name-label> (1) <super-type>base:structured</super-type> <form> <input type="TextLine" name="otherNames"> <label>Other names</label> <help-text>Other names for this species.</help-text> <occurrences minimum="0" maximum="0" /> </input> <input name="images" type="ImageSelector"> <label>Images</label> <help-text>Images of the animal</help-text> <occurrences minimum="0" maximum="3" /> </input> </form> </content-type>
1 This field lets you customize what Content Studio calls the "display name" field and what it puts in the placeholder text. -
Next, update the
Artist
content type.An updated artist<content-type> <display-name>Artist</display-name> <description>Information about an artist</description> <super-type>base:structured</super-type> <form> <input name="name" type="TextLine"> <label>Name</label> <help-text> The artist's name (if different from their professional moniker). </help-text> </input> <input type="TextArea" name="about"> <label>About the artist</label> </input> <input name="favoriteAnimal" type="ContentSelector"> (1) <label>Favorite animal</label> <config> <allowContentType>animal</allowContentType> <allowPath>${site}/animals/</allowPath> </config> </input> </form> </content-type>
1 This ContentSelector uses the config
section to narrow the possible types of content to only beAnimal
-
Create some animals. Either pick your favorites, or, if you’re not feeling creative, add these (content from Wikipedia), :
Lion (Wiki article for lion)- Name
-
Lion
- Description
-
The lion (Panthera leo) is a species in the family Felidae and a member of the genus Panthera. It has a muscular, deep-chested body, short, rounded head, round ears, and a hairy tuft at the end of its tail.
- Name
-
Reindeer, Caribou
- Description
-
The reindeer (Rangifer tarandus), also known as caribou in North America, is a species of deer with circumpolar distribution, native to Arctic, sub-Arctic, tundra, boreal, and mountainous regions of northern Europe, Siberia, and North America.
-
Create some links using ContentSelector from artists to animals to get familiar with linking content.
Headless: fetching linked content and images
Finally, it’s time to introduce the grapqh in GraphQL. A ContentSelector input will store a reference to the target content item. When using the Guillotine API, you may simply follow this reference to access the target content, and access it’s fields instantly.
{
guillotine {
getChildren(key: "${site}/artists/")
{
displayName
... on com_example_myproject_Artist {
data {
name
favoriteAnimal {
displayName
... on com_example_myproject_Animal{
data {
otherNames
}
}
}
}
}
}
}
}
Depending on the links (and animals) you created, your result might look a little something like this:
{
"data": {
"guillotine": {
"getChildren": [
{
"displayName": "Cardi B",
"data": {
"name": "Belcalis Marlenis Almánzar",
"favoriteAnimal": {
"displayName": "Reindeer",
"data": {
"otherNames": [
"Caribou"
]
}
}
}
},
{
"displayName": "Missy Elliott",
"data": {
"name": "Melissa Arnette Elliott",
"favoriteAnimal": {
"displayName": "Lion",
"data": {
"otherNames": []
}
}
}
},
{
"displayName": "P!nk",
"data": {
"name": "Alecia Beth Moore",
"favoriteAnimal": {
"displayName": "Reindeer",
"data": {
"otherNames": [
"Caribou"
]
}
}
}
}
]
}
}
}