Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
How to amend the built-in behavior of adding fields and associating workflows with new forms
By default, a single workflow is added when a new form is created. This workflow will send a copy of the form to the email address of the current backoffice user.
A single "data consent" field will also be added unless it has been disabled via configuration.
It's possible to amend this behavior and change it to fit your needs.
Two interfaces are used to abstract the logic for setting default fields and workflows for a form. They are IApplyDefaultFieldsBehavior
and IApplyDefaultWorkflowsBehavior
respectively.
The default behaviors are defined using built-in, internal classes that implement this interface.
You can create your own implementation of these interfaces.
An illustrative example, adding a custom workflow that writes to the log, is shown below.
Firstly, the custom workflow:
Secondly, the custom implementation of IApplyDefaultWorkflowsBehavior
:
Finally, to register the custom implementation in place of the default one:
When adding a default workflow in code, it's possible to make it mandatory, which will prevent editors from removing it from a form.
You can see this in the example above, where the IsMandatory
property of the created FormWorkflowWithTypeSettings
instance is set to true
.
The following class shows the default implementation provided with Forms. You can copy this and customize it to your needs.
Again, you will need to register your custom class, for example, in a composer with:
Umbraco Forms functionality can be extended in different ways. In this section we focus on techniques available to a back-end/C# developer.
For front-end extensions, specifically via theming, see the Themes section.
Although the Forms package comes with many fields, workflows and other built-in types, you can still create and develop your own if needed.
Many features of Forms use a provider model, which makes it quicker to add new parts to the application.
The model uses the notion that everything must have a type to exist. The type defines the capabilities of the item. For instance a Textfield on a form has a FieldType, this particular field type enables it to render an input field and save text strings. The same goes for workflows, which have a workflow type, datasources which have a datasource type and so on. Using the model you can seamlessly add new types and thereby extend the application.
It is possible to add new Field types, Data Source Types, Prevalue Source Types, Export Types, and Workflow Types.
A field type handles rendering of the UI for a field in a form. It renders a standard ASP.NET Razor partial view and is able to return a list of values when the form is saved.
The concept of provider settings, common to the field and other types, is also discussed in this section.
A data source type enables Umbraco Forms to connect to a custom source of data. A data source consists of any kind of storage if it is possible to return a list of fields Umbraco Forms can map values to. For example: a Database data source can return a list of columns Forms can send data to. This enables Umbraco Forms to map a form to a data source. A data source type is responsible for connecting Forms to external storage.
A prevalue source type connects to 3rd party storage to retrieve values. These values are used on fields supporting prevalues. The source fetches the collection of values.
A workflow can be executed each time a form changes state (when it is submitted for instance). A workflow is responsible for executing logic which can modify the record or notify 3rd party systems.
Export types are responsible for turning form records into any other data format, which is then returned as a file.
Custom magic string format functions to add to the ones shipped with Umbraco Forms can be created in code.
When creating a text field in Umbraco Forms, a validation pattern in the form of a regular expression can be applied. Default patterns can be removed or re-ordered, and custom ones created and added.
Another option for extension via custom code is to hook into one of the many events available.
Form events are raised during the submission life cycle and can be handled for executing custom logic.
When a new form is created, the default behavior is to add a single workflow. This workflow will send a copy of the form to the current backoffice user's email address.
A single "data consent" field will also be added unless it has been disabled via configuration.
It's possible to amend this behavior and change it to fit your needs.
In the course of submitting a form, Umbraco Forms will set values in TempData
and/or HttpContext.Items
, that you can use to customize the website functionality.
Whether displaying a message or redirecting, a developer can customize the page viewed after the form is submitted based on the presence of TempData
variables.
One variable with a key of UmbracoFormSubmitted
has a value containing the Guid identifier for the submitted form.
A second variable contains the Guid identifier of the record created from the form submission. You can find this using the Forms_Current_Record_id
key.
In order to redirect to an external URL rather than a selected page on the Umbraco website, you will need to use a custom workflow. Within this workflow you can set the required redirect URL on the HttpContext.Items
dictionary using the key FormsRedirectAfterFormSubmitUrl
(defined in the constant Umbraco.Forms.Core.Constants.ItemKeys.RedirectAfterFormSubmitUrl
).
For example, using an injected instance of IHttpContextAccessor
:
Umbraco Forms comes with some built-in fields however it is possible to exclude/remove them if necessary. There might some use cases where you have no use for file upload and don't want editors using them. Or perhaps you want to remove a field to replace it with one with enhanced functionality that you build yourself.
The following class shows how to exclude built-in field types using a custom composer. The Password
, Recaptcha2
and RichText
field types (or "answers") will no longer be available for selection when creating a form in the backoffice.
To add a new type, no matter if it's a workflow, field, data source, etc, there is a number of tasks to perform to connect to the Forms provider model. This chapter walks through each step and describes how each part works. This chapter will reference the creation of a workflow type. It is, however, the same process for all types.
Create a new class library project in Visual Studio add references to the Umbraco.Forms.Core.dll
(available via referencing the NuGet package). You might also need to reference Umbraco.Forms.Core.Providers.
The Forms API contains a collection of classes that can be registered at startup or in an Umbraco component. So to add a new type to Forms you inherit from the right class. In the sample below we use the class for the workflow type.
When you implement this class you get two methods added. One of them is Execute which performs the execution of the workflow and the other is a method which validates the workflow settings, we will get back to these settings later on.
Any dependencies required that are registered with the dependency injection container can be provided via the constructor.
Even though we have the class inheritance in place, we still need to add a bit of default information.
Even though we have the class inheritance in place, we still need to add a bit of default information. This information is added in the class's constructor like this:
All three are mandatory and the ID must be unique, otherwise the type might conflict with an existing one.
Now that we have a basic class setup, we would like to pass setting items to the type. So we can reuse the type on multiple items but with different settings. To add a setting to a type, we add a property to the class, and give it a specific attribute like this:
The Umbraco.Forms.Core.Attributes.Setting registers the property in Umbraco Forms and there will automatically be UI and storage generated for it. In the attribute, a name, description and the view to be rendered is defined.
With the attribute in place, the property value is set every time the class is instantiated by Umbraco Forms. This means you can use the property in your code like this:
For all types that use the provider model, settings work this way. By adding the Setting attribute Forms automatically registers the property in the UI and sets the value when the class is instantiated.
Each setting value is stored as a string with the user interface for generating the value defined via the View
property.
Umbraco Forms ships with setting types and you can also create your own.
The ValidateSettings()
method which can be found on all types supporting dynamic settings, is used for making sure the data entered by the user is valid and works with the type.
To register the type, ensure your web application project has a reference to the class library, either via a project or NuGet reference. Then add the following code into the startup pipeline. In this example, the registration is implemented as an extension method to IUmbracoBuilder
and should be called from Program.cs
:
An alternative approach is to use a composer, as per this example:
There are further convenience methods you can use for registering custom types. These are found in the namespace Umbraco.Forms.Core.Providers.Extensions
.
For example, instead of the following:
Your workflow can be registered using:
Or:
Existing items that are not required in a particular installation can be removed with:
Also look in the reference chapter for complete class implementations of workflows, fields and export types.
It is possible to override and inherit the original provider, be it a Field Type or Workflow etc. The only requirement when inheriting a fieldtype that you wish to override is to ensure you do not override/change the Id set for the provider, and make sure your class is public.
Here is an example of overriding the Textarea field aka Long Answer.
As discussed in the previous section, you must also register the extended field type within a composer. You also need to create the the backoffice field type view.
Composer:
Backoffice View:
Add a new HTML file as per the name of the field class (e.g. textareawithcount.html
) to \wwwroot\App_Plugins\umbracoforms\Backoffice\Common\FieldTypes\
within your project. For this example, we can copy the original textarea.html
file used by the standard 'Long Answer' field.
The AngularJS client-side files are shipped with Umbraco Forms as part of a Razor Class Library. So you won't find these files on disk when you install the package.
However if you do want to reference them you can view and extract them from the Umbraco.Forms.StaticAssets
NuGet package.
See an example of validating a form server-side
Add a new class to your project as a handler for the FormValidateNotification
notification:
The handler will check the ModelState
and Form
field values provided in the notification. If validation fails, we add a ModelError
.
To register the handler, add the following code into the startup pipeline. In this example, the registration is implemented as an extension method to IUmbracoBuilder
and should be called from Program.cs
:
The services available via interfaces IFormService
, IFolderService
, IDataSourceService
and IPrevalueSourceService
trigger following notifications before or after an entity handled by the service is modified.
The "-ing" events allow for the entity being changed to be modified before the operation takes place, or to cancel the operation. The "-ed" events fire after the update is complete.
Both can be wired up using a composer and component:
When a form or folder is moved there is no specific service event. However, information available in the State
dictionary on the notification object can be used to determine whether the item was moved. If so, it can show where it was moved from:
If a folder is being moved, the key within the State
dictionary is "MovedFromParentId"
.
When an entry for a form is rendered in the backoffice, an event is available to allow modification of the record detail. This event is available before the record details are presented to the user. This is shown in the following example:
This builds on the "adding a type to the provider model" chapter
Umbraco Forms Magic Strings can be used to replace placeholders within form elements with values from different sources. Sources include the HTTP request or the Umbraco page where the form is hosted.
These values can be formatted using filter functions.
Filter functions for common operations such as truncating a string or formatting a date or number are provided. It's also possible to create custom ones in code.
To create a custom format function, create a class that implements IParsedPlaceholderFormatter
.
The FunctionName
property provides the name of the function that will be used within the form's magic string.
The FormatValue
property parses the provided value and arguments and returns the formatted value as a string.
The following example shows the implementation of a function that bounds an integer value. It takes two arguments, a minimum and maximum value. If the value read from the magic string source is numeric, and fits within the two bounds, it is returned. Otherwise, either the minimum or maximum value is returned depending on whether the value is lower or higher than the bounds respectively.
As with other provider types, the custom function needs to be registered. An example registration using the IUmbracoBuilder
is shown below:
The format function can be used within a form's magic string in the same way as the ones provided with Umbraco Forms.
For the example provided, it would be used like this:
This builds on the "adding a type to the provider model" chapter
Add a new class to your project and have it inherit from Umbraco.Forms.Core.WorkflowType
, and implement the class. For this sample, we will focus on the execute method. This method processes the current record (the data submitted by the form) and have the ability to change data and state.
The ExecuteAsync()
method gets a WorkflowExecutionContext
which has properties for the related Form
, Record
, and FormState
. This parameter contains all information related to the workflow.
The Record
contains all data and metadata submitted by the form. As shown in the example above, you can iterate over all RecordField
values in the form. You can also retrieve a specific record field by alias using the following method:
Having obtained a reference to a record field, the submitted value can be retrieved via:
The ValuesAsString
will JSON escape the result by default. If you do not want this escaping to occur, pass false
as the parameter.
If the field stores multiple values, they are delimited with a comma. In many cases, you can safely split on that delimiter to obtain the individual values. However, this can lead to issues if the prevalues being selected also contain commas. If that's a concern, the following extension method is available in Umbraco.Forms.Core.Extensions
to correctly parse the selected prevalues:
The Form
references the form the record is from and FormState
provides its state (submitted or approved).
Other context, such as the current HttpContext
, if needed can be passed as constructor parameters (for example: the HttpContext
can be accessed by injecting IHttpContextAccessor
).
To use the new workflow type, you will need to register it as part of application startup.
This builds on the "adding a type to the provider model" chapter.
Add a new class to your project and have it inherit from Umbraco.Forms.Core.ExportType
. You have two options when implementing the class, as shown in the following examples.
You can implement the method public override string ExportRecords(RecordExportFilter filter)
in your export provider class. You need to return a string you wish to write to a file. For example, you can generate a .csv
(comma-separated values) file. You would perform your logic to build up a comma-separated string in the ExportRecords
method.
In the constructor of your provider, you will need a further two properties, FileExtension
and Icon
.
FileExtension
is the extension such as zip
, txt
or csv
of the file you will be generating and serving from the file system.
In this example below we will create a single HTML file which takes all the submissions/entries to be displayed as a HTML report. We will do this in conjunction with a Razor partial view to help build up our HTML and thus merge it with the form submission data to generate a string of HTML.
This approach gives us more flexibility in creating the file we wish to serve as the exported file. We do this for the export to Excel file export provider we ship in Umbraco Forms. With this we can use a library to create the Excel file and store it in a temporary location before we send back the filepath for the browser to stream down the export file.
In this example we will create a collection of text files, one for each submission which is then zipped up into a single file and served as the export file.
This builds on the "Adding a type to the provider model" article
Add a new class to your project - inherit it from Umbraco.Forms.Core.FieldPreValueSourceType
and implement the class.
The following example shows an illustrative custom prevalue source type that returns a hard-coded list of values. It can be extended for your needs via injection of services via the constructor. (See additional example at the bottom.)
Dynamic settings can be applied and validated as shown in the Validate type settings with ValidateSettings() article.
You will then need to register this new prevalue source type as a dependency.
The PreValue
model in Umbraco Forms Versions 8.13.0, 9.5.0, 10.1.0, and above includes a .Caption
property. This property is set separately from the .Value
property. In the previous versions, the Value
is generally used as the caption when rendered on the form.
This example will take a user-provided Content Node and create a custom Prevalue list from the property data on that node. Your own FieldPreValueSourceType
can get its data from wherever you like - an API call, custom functions, etc.
You will then need to register this new type as a dependency (either in Program.cs
or in your own IComposer, as shown here).
This builds on the "adding a type to the provider model" chapter
In this article, we will illustrate how to add a custom form field type using server-side and client-side components. We will use the example of rendering a "slider" field type that allows the user to select a number within a specific range of values.
Add a new class to the Visual Studio solution. Inherit from Umbraco.Forms.Core.FieldType
and complete as follows:
In the constructor or via overridden properties, we can specify details of the field type:
Id
- should be set to a unique GUID.
Alias
- an internal alias for the field, used for localized translation keys.
Name
- the name of the field presented in the backoffice.
Description
- the description of the field presented in the backoffice.
Icon
- the icon of the field presented in the backoffice form builder user interface.
DataType
- specifies the type of data stored by the field. Options are String
, LongString
, Integer
, DataTime
or Bit
(boolean).
SupportsMandatory
- indicates whether mandatory validation can be used with the field (defaults to true
).
MandatoryByDefault
- indicates whether the field will be mandatory by default when added to a form (defaults to false
).
SupportsRegex
- indicates whether pattern-based validation using regular expressions can be used with the field (defaults to false
).
SupportsPreValues
- indicates whether prevalues are supported by the field (defaults to false
).
RenderInputType
- indicates how the field should be rendered within the theme as defined with the RenderInputType
enum.
The default is Single
for a single input field.
Multiple
should be used for multiple input fields such as checkbox lists.
Custom
is used for fields without visible input fields.
FieldTypeViewName
- indicates the name of the partial view used to render the field on the website.
EditView
- indicates the name of a property editor UI that is used for editing the field in the backoffice. If nothing is provided, the built-in label will be used and the field won't be editable.
PreviewView
- indicates the name of a manifest registered client-side resource that is used for previewing the field in the backoffice. If nothing is provided, the name of the field type will be used as the preview.
You now need to register this new field as a dependency:
We will start building the view for the default theme of the Form at Views\Partials\Forms\Themes\default\FieldTypes\FieldType.Slider.cshtml
.
The file name for the partial view should match the value set on the FieldTypeViewName
property.
This will be rendered when the default theme is used.
If working with Umbraco 9 or earlier versions, you'll find the Views\Partials\Forms\Themes\default\
folder on disk and can create the files there.
For Umbraco 10 and above, we've moved to distributing the theme as part of a Razor Class Library so the folder won't exist. However, you can create it for your custom field type. If you would like to reference the partial views of the default theme, you can download them as mentioned in the Themes article.
When rendering a multi-page form, editors have the option to display a summary page where the entries can be viewed before submitting.
To support this, a read-only view of the field is necessary.
For most fields, nothing is required here, as the default read-only display defined in the built-in ReadOnly.cshtml
file suffices.
However, if you want to provide a custom read-only display for your field, you can do so by creating a second partial view. This should be named with a .ReadOnly
suffix. For this example, you would create FieldType.Slider.ReadOnly.cshtml
.
Field settings will be managed in the backoffice by editors who will create forms using the custom field type. These settings can be added to the C# class as properties with a Setting
attribute:
The property Name
names the setting in the backoffice with the Description
providing the help text. Both of these can be translated, as discussed in the backoffice components section below.
The View
property indicates a property editor UI used for editing the setting value. You can use a built-in property editor UI, one from a package, or a custom one registered with your solution. The default value if not provided is Umb.PropertyEditorUi.TextBox
, which will use the standard Umbraco text box property editor UI.
SupportsPlaceholders
is a flag indicating whether the setting can contain "magic string" placeholders and controls whether they are parsed on rendering.
HtmlEncodeReplacedPlaceholderValues
takes effect only if SupportsPlaceholders
is true
. It controls whether the replaced placeholder values should be HTML encoded (as is necessary for rendering within content from a rich text editor).
SupportsHtml
is a flag indicating whether the setting can contain HTML content. When set to true
it will be treated as HTML content when the value is read from the Forms delivery API.
IsMandatory
if set to true
will provide client-side validation in the backoffice to ensure the value is completed.
When creating a field or other provider type, you might choose to inherit from an existing class. This could be if one of the types provided with Umbraco Forms almost meets your needs but you want to make some changes.
All setting properties for the Forms provider types are marked as virtual
, so you can override them and change the setting values:
With Forms 14, aspects of the presentation and functionality of the custom field are handled by client-side components, registered via manifests:
The preview, displayed on the form definition editor.
The property editor UI used for editing the the submitted values via the backoffice.
The property editor UI used for editing settings.
A settings converter, that handles configuring the property editor and translating between the editor and persisted values.
Translations for setting labels and descriptions.
To display a name and description on a custom field, you need to register a JavaScript file as shown in the Localization article.
The alias of the preview to use is defined on the field type via the PreviewView
property.
A preview for our slider, representing the selected setting values could look as follows:
And it is registered via a manifest:
Umbraco Forms supports editing of the entries submitted by website visitors via the backoffice. The property editor interface to use for this is defined in the field type's EditView
property.
If not using a built-in property editor, you can create your own. The following example shows how the numerical entries could be edited using an input control.
Again, it's registered via a manifest.
Field type settings also use a property editor UI for editing the values in the backoffice. The one to use is defined via the View
property on the Setting
attribute.
In our example we use a custom one, allowing the value for the background color to the field to be selected via an input control.
And register it via a manifest:
You may want to consider registering a settings value converter. This is another client-side component that is registered in a manifest. It converts between the setting value required for the editor and the value persisted with the form definition. A converter defines three methods:
getSettingValueForEditor
- converts the persisted string value into one suitable for the editor
getSettingValueForPersistence
- converts the editor value into the string needed for persistence
getSettingPropertyConfig
- creates the configuration needed for the property editor
The following code shows the structure for these converter elements.
It's registered as follows. The propertyEditorUiAlias
matches with the property editor UI that requires the conversions.
Setting labels and descriptions are translated via language files. The following example shows how this is created for the settings on our example field type:
Each different type of extension for Forms uses a different root value:
Data sources - formProviderDataSources
Export types - formProviderExportTypes
Field types - formProviderFieldTypes
Prevalue sources - formProviderPrevalueSources
Recordset actions - formRecordSetActions
Workflows - formProviderWorkflows
The language files are registered with:
Finally, you will need an entry point to your client-side components that will register the manifests with Umbraco's extension registry. For example:
Customize the regular expression based validation patterns available for text fields.
When creating a text field in Umbraco Forms, a validation pattern in the form of a regular expression can be applied. Default patterns can be removed or re-ordered, and custom ones created and added.
Umbraco Forms ships with three patterns: number, email, and URL. The class names are Number
, Email
, and Url
respectively, and all are found in the Umbraco.Forms.Core.Providers.ValidationPatterns
namespace.
To create a custom format function, create a class that implements IValidationPattern
. You will need to initialize five properties:
Alias
- an alias that should be unique across the patterns and is typically camel-cased with no spaces.
Name
- the name of the pattern that will be visible in the backoffice.
LabelKey
- as an alternative to providing a name, a translation key can be provided. This will be used to look-up the name in the correct language for the backoffice user.
Pattern
- the regular expression pattern.
ReadOnly
- a flag indicating whether the pattern can be edited in the backoffice.
The following example shows the implementation of a pattern for a United Kingdom postcode (credit for the pattern to Mecanik at StackOverflow).
As with other provider types, the validation pattern needs to be registered. There are options to add, remove, and re-order patterns.
An example registration using the IUmbracoBuilder
is shown below:
With the pattern registered it will be available for selection by editors in the backoffice when they create validation for fields supporting this feature.
Umbraco Forms field, prevalue source and workflow types are defined in C# and include one or more setting values.
These settings are completed by the editor when using the type on their form.
Each setting type can have it's own user interface. So a string can use a text box but a more complicated JSON structure can use a more appropriate user interface.
From Forms 14, each interface is defined as an Umbraco property editor UI.
The user interface used for a particular setting is defined by the View
property:
If not specified, the default Umb.PropertyEditorUi.TextBox
is used.
The following setting types are available and are used for the field, prevalue source and workflow types that ship with the package.
Some are defined with the Umbraco CMS and some ship with the Forms package.
Name | Source | Description | Used in |
---|---|---|---|
All of the above setting types are used in one or more field, prevalue source and workflow types available with Umbraco Forms. For the less common ones, a usage has been indicated in the table.
The one exception is Forms.PropertyEditorUi.TextWithFieldPicker
. This one we don't use within the package, but we make it available for developers to use when creating their own types.
It offers the option of text field entry or the selection of a field from the form. This can be useful in workflows where you need to reference the value of a specific field.
To create a custom setting type you will need an AngularJS view and controller in the following location: /App_Plugins/MyPlugin/
.
Your plugin folder path must be outside of the /App_Plugins/UmbracoForms/
folder if you use a custom Angular controller and Package.manifest.
You then add the name of the view as the View
property on the Setting
attribute defined on the type.
To create custom backoffice components for Umbraco 14, it's recommended to use a front-end build setup using Vite, TypeScript, and Lit. For more information, see the article.
Umb.PropertyEditorUi.ContentPicker.Source
CMS
Uses a content picker with the option for XPath entry
The "Save as Umbraco node" workflow
Umb.PropertyEditorUi.Dropdown
CMS
Used for selection from a list of options
Umb.PropertyEditorUi.Integer
CMS
Uses numerical text box for entry
Umb.PropertyEditorUi.MediaEntityPicker
CMS
Uses a media item picker for entry
The "Send email with XSLT template" workflow
Umb.PropertyEditorUi.MultipleTextString
CMS
Uses multiple text boxes for entry
Not used in core types
Umb.PropertyEditorUi.Slider
CMS
Uses a slider for range input
The "reCAPTCHAv3" field type
Umb.PropertyEditorUi.TextArea
CMS
Uses a multiline textbox for entry
Umb.PropertyEditorUi.TextBox
CMS
Uses a single-line textbox for entry
Umb.PropertyEditorUi.TinyMCE
CMS
Uses a rich text editor for input
The "Send email" workflows
Umb.PropertyEditorUi.Toggle
CMS
Uses a single checkbox for entry
Umb.PropertyEditorUi.UploadField
CMS
Used for selection of a file
The "Text file" prevalue source
Forms.PropertyEditorUi.DataTypePicker
Forms
Uses a datatype picker
The "Umbraco prevalues" prevalue source
Forms.PropertyEditorUi.DocumentTypePicker
Forms
Uses a Document Type picker
The "Umbraco nodes" prevalue source
Forms.PropertyEditorUi.DocumentTypeFieldPicker
Forms
Uses to select fields from a Document Type
The "Umbraco nodes" prevalue source
Forms.PropertyEditorUi.DocumentMapper
Forms
Used for mapping of fields from a Document Type
The "Save as Umbraco node" workflow
Forms.PropertyEditorUi.EmailTemplatePicker
Forms
Used for selection of an email template
The "Send email with Razor template" workflow
Forms.PropertyEditorUi.FieldMapper
Forms
Used to map fields from a form to required aliases
The "Send to URL" workflow
Forms.PropertyEditorUi.Password
Forms
Uses password text box for entry
Forms.PropertyEditorUi.StandardFieldMapper
Forms
Used to map system fields from a form to required aliases
The "Send to URL" workflow
Forms.PropertyEditorUi.TextWithFieldPicker
Forms
Uses a single-line textbox/form field list for entry
Not used in core types