Declarative Forms with OutSystems Developer Cloud


Building forms in OutSystems is incredibly fast. You simply define a structure, add a form element to the canvas, and drag and drop the individual fields into the form. This is excellent for static forms linked to data structures, but only developers can create these forms, and after they're built and tested, the application must be redeployed to production.
In some situations, you might need to build a form dynamically, along with its data model, or even let an end-user define a form and its elements while using the application. Assessments or surveys are good examples of such user-defined forms. Additionally, you could consider dynamically creating a form from an AI model operation result.
In this article, we explore how to implement my Runtime Forms component available on ODC Forge. The library allows you to dynamically describe and render a form. This approach is also called declarative forms, where you specify what the form should look like and how it should behave in a configuration (in this case, a structure), instead of placing individual input elements on the canvas like with static forms.
Demo Application
This article includes a demo application called "Runtime Forms Demo," available on ODC Forge.
In the ODC Portal, go to Forge - All Assets.
Search for "Runtime Forms Demo".
Click on Install.
This demo depends on:
- Runtime Forms - This is the main library you can use and customize for your own applications. It offers a single widget to render a declarative form.
Runtime Forms Introduction
The library you downloaded from ODC Forge includes a single UI widget for rendering a declarative form. Think of it as a starting point that you can improve and customize for your own needs.
It supports the following features:
Renders various input elements based on parameters (Fields) that describe them.
Populates data (Data) into input elements from a JSON document.
Validates the form on submission using HTML5 validation attributes.
Sends form data as a JSON document upon submission (OnSubmit).
Supported Form Elements
The form elements you can use with the widget are limited to the following input types:
Text Inputs
Text - A single-line text field. This is the default value for an input element.
Textarea - A multi-line text field.
Password - A single-line text field where the input is obscured to protect sensitive information.
Email - A field specifically for entering one or more email addresses. Validation ensures that the text entered is a valid e-mail address.
Search - A single-line text field for entering search queries. It may include a control to clear the entered text.
Tel - A field for entering a telephone number. Unlike email, it doesn't enforce a specific syntax, but it may trigger a numeric keypad on mobile devices.
Url - A field for entering a URL. The browser may provide validation to ensure the text is in a valid URL format.
Date and Time Inputs
date - A control for entering a date (year, month, and day).
time - A control for entering a time (hour and minute).
datetime-local - A control for entering both a date and time, without time zone information.
month - A control for entering a month and year.
week - A control for entering a week and year.
Numeric Inputs
- number - A field for entering a number.
Selection Inputs
radio - A radio button that allows the user to select only one option from a group of choices.
checkbox - A checkbox that allows the user to enable or disable.
All input elements are displayed in the order specified by the Fields input parameter of the widget.
Field Configurations and Validations
Input field configurations and validations are divided into two parts: a common set of configuration elements that apply to all supported form elements, and type-specific settings that apply only to individual form element types.
Common
The following settings apply to all types:
Name - The name attribute of the form element. This name also becomes the attribute name of the JSON data document you receive when you submit the form.
Type - The input element's type attribute. The FieldType static entity provides the supported element types as described above.
Label - If present, the widget adds an extra
<label>
tag for the form element.Text - If present, this text is displayed right above the form element. You can use it to add extra descriptions or guidance for the form element.
Placeholder - If present, it sets the placeholder attribute of the form element.
IsRequired - If set to True, it adds the required attribute to the form element, making user input necessary.
IsDisabled - If set to True, it adds the disabled attribute to the form element. When the form is submitted, data from disabled elements is excluded.
IsReadOnly - If set to True, it adds the readonly attribute to the form element. Data from readonly elements is included when the form is submitted.
HasAutoFocus - Sets the autofocus attribute for the form element. Ensure that only one element has autofocus.
TabIndex - Defaults to 0. When set, this configures the tab order of the element.
Type-specific
Type-specific settings are found in the Config object. Depending on the chosen input type, the following settings apply.
For text, textarea, password, email, search, tel and url the following settings apply:
MinLength - Specifies the minimum number of characters the user must enter for the input to be considered valid.
MaxLength - Specifies the maximum number of characters the user can enter into the input field.
Pattern - Specifies a regular expression that the input field's value is checked against. It allows for complex validation rules.
Autocomplete - Specifies whether a browser should automatically complete the input based on values the user has entered previously. Can be set to "on" or "off".
Rows (only applicable to textarea) - The number of rows of the multi-line text input element.
For date, time, datetime-local, month and week:
Min - Specifies the earliest date/time/month/week that can be selected.
Max - Specifies the latest date/time/month/week that can be selected.
For number:
Min - Specifies the minimum allowed value for the input.
Max - Specifies the maximum allowed value for the input.
Step - Specifies the legal number intervals (e.g.,
step="2"
allows 0, 2, 4...).any
allows any value.
For radio and checkbox:
IsChecked - A boolean attribute that specifies if a
checkbox
orradio
button should be selected by default when the page loads.Options (Radio only) - A list of Label/Value pairs for the radio options to select from.
Most of the settings above are related to validation, and the library uses the browser's built-in form validation. You can read more about this client-side form validation on MDN.
Applying and Submitting Data
The Data input parameter lets you add a JSON document as a string. The library attempts to apply the attribute values to the corresponding input elements based on the name.
Consider the following form:
A text field named fullName
A checkbox field named isMember
A radio field shirtSize with the Label/Value pairs
[Small - S]
,[Large - L]
, and[X-Large - XL]
The JSON document to apply all values would look like this:
{
"fullName": "Stefan Weber",
"isMember": true,
"shirtSize": "XL"
}
Similarly, when you submit the form, you will receive an equivalent JSON document as the OnSubmit payload.
Library Limits
By the time of writing the Runtime Forms library does not support
Validations for Radio buttons.
Conditional visibility of form elements.
Demo Walkthrough
Let's take a closer look at how this works. In ODC Studio, open the Runtime Forms Demo application.
In the Logic tab, open the BuildSampleForm server action. This action is designed to create individual form elements using the FieldDefinition structure. It returns a list of FieldDefinition that serve as input parameters for the library's RuntimeForm widget.
Check the various configurations of the field elements.
In the Interface tab open the Run screen.
The GetFormDefinition data action executes the BuildSampleForm server action. The result of the data action is bound to the Fields input parameter of the RuntimeForm widget.
The local DataEntry variable is linked to the JSON Data textarea on the right side of the screen. When you click the Apply Data button (triggering the ApplyDataOnClick client action), the content of this variable is assigned to the DataSubmitted variable, which is bound to the Data input parameter of the widget.
When running the demo you will see the following screen.
Hit the Apply Data button for applying the provided JSON data to the form.
Leave the Company Mail Address empty and click the Submit button. Note the validation error message below the mail address.
Enter a invalid value into the mail address field e.g.
me@
and note the validation message.Fill in all required fields and click the Submit button. Note the JSON data in the Last Submitted JSON data area.
Add and modify Field definitions in the BuildSampleForm server action.
Library Modifications
As mentioned above, you may need to adjust the library to fit your needs, such as adding custom client-side validations or additional form elements. Take a look at the RuntimeForms library, especially the following:
RuntimeForm widget
ValidateForm client action - Validates all non-disabled field elements. If you want to customize or extend browser-based validation, this is where you can do it.
PopulateFormData client action - Fills the individual field elements with the provided data.
SubmitOnClick - Triggers the OnSubmit event with the form data as the payload.
RuntimeFormField
- ApplyFieldConfiguration client action - This action applies type-specific field attributes to the elements (e.g., required, minLength, etc.).
Summary
This article introduces the Runtime Forms library, available on ODC Forge, which enables dynamic form creation in OutSystems Developer Cloud applications. Unlike static forms, Runtime Forms allow developers or even end-users to define and render forms on-the-fly using a declarative approach. The component supports various input types and validations.
I hope you enjoyed it and would appreciate your feedback.
Subscribe to my newsletter
Read articles from Stefan Weber directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Stefan Weber
Stefan Weber
Throughout my diverse career, I've accumulated a wealth of experience in various capacities, both technically and personally. The constant desire to create innovative software solutions led me to the world of Low-Code and the OutSystems platform. I remain captivated by how closely OutSystems aligns with traditional software development, offering a seamless experience devoid of limitations. While my managerial responsibilities primarily revolve around leading and inspiring my teams, my passion for solution development with OutSystems remains unwavering. My personal focus extends to integrating our solutions with leading technologies such as Amazon Web Services, Microsoft 365, Azure, and more. In 2023, I earned recognition as an OutSystems Most Valuable Professional, one of only 80 worldwide, and concurrently became an AWS Community Builder.