Adding server-side validation for a Property Editor.
When creating Property Editors, our intended audience is trusted (logged-in) backoffice users. Therefore, we can rely on client-side validation of user inputs. However, there are occasions when server-side validation is necessary as well.
Server-side validation is performed by implementing a Data Editor, which is the server-side pendent to the Property Editor.
In this article, we will implement server-side validation for the Suggestion
Property Editor created in the previous steps.
As mentioned above, server-side validation is the most common use-case for implementing a Data Editor.
Less common use-cases include:
Custom content indexing for search,
Server-side conversion of the data that is passed to - and received from - the Property Editor UI,
and more.
These will be discussed briefly at the end of this article.
Validation is initiated by the Data Editor, but the actual handling is performed in a Data Value Editor implementation:
The Data Value Editor in turn employs Value Validators to handle specific aspects of validation. Usually we'll create our own Value Validator implementations, but we could also reuse the ones in Umbraco (for example, the EmailValidator
).
The Value Validator performs validation based on the user input from the Property Editor along with the configuration of the Data Type:
With the Data Editor in place, update the Property Editor propertyEditorSchemaAlias
in umbraco-package.json
to match the Data Editor alias (My.DataEditor.Suggestions
):
Reload the backoffice and open the "Suggestions" Data Type:
The Umbraco UI already lists the Data Type as using the Data Editor. However, the Data Type configuration is still stored in the database using Umbraco.Plain.String
. To effectively apply the Data Editor, we must re-save the Data Type.
As mentioned earlier, the Data Editor has more use-cases than adding server-side validation.
While it is beyond the scope of this article to discuss these in depth, a few of them deserve a mention.
We can control how property data is indexed by overriding the PropertyIndexValueFactory
property of the DataEditor
base class.
The Tags Property Editor contains an example of how this is done. The Property Editor stores a CSV value, which is split and indexes as individual tags for search.
Sometimes it is necessary to perform outbound and/or inbound conversion of property data (to/from the Property Editor UI). Some known use-cases are:
Cleaning up property data - for example, removing previously selected options that no longer apply at server level.
Transforming property data to/from a format supported by the Property Editor UI.
These operations can be performed in the DataValueEditor
implementation:
Override ToEditor()
to perform outbound conversion.
Override FromEditor()
to perform inbound conversion.
The Markdown Property Editor contains an example of data conversion. It sanitizes the property data before storing the data in the database.
Add a Property Value Converter for custom Property Editor value conversion.
In the previous steps, we created a custom Property Editor for the Umbraco backoffice client. In this step, we will discuss how to convert the Property Editor values for use when rendering the website.
To this end, we will create a Property Value Converter that converts the stored suggestion text into a custom rendering model.
A Property Value Converter is usually not necessary. Based on the chosen propertyEditorSchemaAlias
, Umbraco will automatically provide appropriately typed models for rendering the Property Editor. For more information, see the Default Property Editor Schema Alias options article.
The most common use-cases for building a Property Value Converter are:
Property Editors that store values which require server-side conversion, in order to render an appropriate output.
Property Editors with specific caching requirements.
Tailoring the Property Editor output value specifically for the Content Delivery API.
A Property Value Converter must meet a few required responsibilities:
Identifying itself as being able to convert values for a given Property Editor.
Declaring the concrete runtime type it will be outputting.
Performing the value conversion from the stored
The following code snippet outlines how these could be solved for our suggestion
Property Editor.
We have used the property type editor UI alias from umbraco-package.json
in the implementation of IsConverter()
.
For more advanced Property Value Converter techniques (for example, controlling caching), see the Property Value Converters article.
Integrate one of the built-in Umbraco Contexts.
This is the third step in the Property Editor tutorial. In this part, we will integrate built-in Umbraco Contexts. For this sample, we will use the UmbNotificationContext
for some pop-ups and the UmbModalManagerContext
. UmbNotificationContext
is used to show a dialog when you click the Trim button and the textbox's input length is longer than the maxLength configuration.
The steps we will go through in this part are:
Add the following imports in the suggestions-property-editor-ui.element.ts
file. This includes the notification context.
Update the class to extend from UmbElementMixin. This allows us to consume the contexts that we need:
Create the constructor where we can consume the notification context above the render()
method:
Now we can use the notification context, let's change our #onTrimText
method.
First, check if the length of our input is smaller or equal to our maxLength configuration. If it is, we have nothing to trim and will send a notification saying there is nothing to trim.
Here we can use the NotificationContext's peek method. It has two parameters UmbNotificationColor
and anUmbNotificationDefaultData
object.
Add the #onTextTrim()
method above the render()
method:
Add a click
event to the trim text button in the render()
method:
If our input length is less or equal to our maxLength configuration, we will now get a notification when pressing the Trim button.
Let's continue to add more logic. If the length is more than the maxChars
configuration, we want to show a dialog for the user to confirm the trim.
Here, we use the ModalManagerContext
which has an open method to show a dialog.
Like the notification context, we need to import it and consume it in the constructor.
Add the following import in the suggestions-property-editor-ui.element.ts
file:
Remove the UmbNotificationContext
from the "@umbraco-cms/backoffice/notification"
import:
Update the constructor to consume the UMB_MODAL_MANAGER_CONTEXT
and the UMB_CONFIRM_MODAL.
Add more logic to the onTextTrim
method:
Run the command npm run build
in the suggestions
folder.
Run the project.
Go to the Content section of the Backoffice.
Ask for suggestions and click on the Trim text button. If the suggested text is long enough to be trimmed, you will be asked for confirmation:
Over the previous steps, we have:
Created a plugin.
Defined an editor.
Registered the Data Type in Umbraco.
Added configuration to the Property Editor.
Connected the editor with UmbNotificationContext
and UmbModalManagerContext
.
Looked at some of the methods from notification & modal manager contexts in action.
Integrated one of the built-in Umbraco Contexts with the Property Editor.
A guide to creating a property editor in Umbraco.
This guide explains how to set up a property editor and hook it into Umbraco's Data Types. It also covers the creation of a basic property editor and how we can test our property editor.
The steps we will go through in part one are:
This tutorial uses Typescript and Lit with Umbraco, It is expected that your package is already set up to use Typescript and Lit.
To see how to set up an extension in Umbraco using Typescript and Lit, read the article Creating your first extension.
This tutorial will not go in-depth on how Typescript and Lit work. To learn about Typescript and Lit, you can find their documentation below:
At the tutorial's end, we'll have a Umbraco Suggestions Data Type, registered in the backoffice, and assigned to a Document Type. This Data Type can create and suggest values.
At each step, you will find a dropdown for suggestions-property-editor-ui.element.ts and umbraco-package.json
to confirm your placement for code snippets.
Follow the Vite Package Setup by creating a new project folder called "suggestions
" in App_Plugins
.
Then create the manifest file named umbraco-package.json
at the root of the suggestions
folder. Here we define and configure our dashboard.
Add the following code to umbraco-package.json
:
The umbraco-package.json
files are cached by the server. When creating new umbraco-package.json
files, it might take a few seconds before those are loaded into the server cache.
It is important to select the right propertyEditorSchemaAlias
as it affects how the Property Editor data is made available when rendering the website.
In this example, we selected the Umbraco.Plain.String
because we want a string value. For more options, see the default Property Editor Schema aliases article.
Now let's create the web component we need for our property editor.
Create a file in the src
folder with the name suggestions-property-editor-ui.element.ts
In this new file, add the following code:
In the vite.config.ts
file replace the entry
to our newly created .ts
file:
Now our basic parts of the editor are done, namely:
The package manifest, telling Umbraco what to load
The web component for the editor
Reload the backoffice.
Add our newly added property editor "Suggestions" in the Document Type and save it.
We can now edit the assigned property's value with our new property editor.
Check out the content where you will see the property editor that looks like this:
Let's start by creating an input field and some buttons that we can style and hook up to events.
Update the render method to include some input fields and buttons in the suggestions-property-editor-ui.element.ts
file:
The Umbraco UI library is already a part of the backoffice, which means we can start using it.
Add some styling. Update the import from lit to include CSS:
Add the CSS:
It should now look something like this:
It's starting to look good! Next, let's look into setting up the event logic.
Let's start with the input field. When we type something in the input field, we want the property editor's value to change to the input field's current value.
We then have to dispatch an property-value-change
event which can be done in two ways:
Using new CustomEvent('property-value-change')
or
Using new UmbPropertyValueChangeEvent()
which is recommended as you can leverage the core class
Add the import so the event can be used:
Add the event to the property editor:
Let's look at the suggestions button next.
When we press the suggestion button we want the text to update to the suggestion that we get. Similar to how the value of our property editor changes when we write in the input field.
We also want the value to change when we press the suggestion button.
Update the import for Lit:
Add suggestions to the property editor:
Update the suggestion button in the render method to call a onSuggestion
method when we press the button:
Clear your cache, reload the document, and see the Suggestions Data Type running.
When we save or publish, the value of the Data Type is now automatically synced to the current content object and sent to the server.
Learn more about extending this service by visiting the Property Editors page.
With all the steps completed, we have created a Suggestion data type running in our property editor.
In the next part, we will look at adding configurations to our property editor.
Adding configuration options to the editor.
This is step two in our guide to building a Property Editor. This step continues work on the Suggestion Data Type we built in part one but goes further to show how to add configuration options to our editor.
The steps we will go through in the second part are:
An important part of building good Property Editors is to build something flexible, so we can reuse it many times, for different things. Like the Rich Text Editor in Umbraco, which allows us to choose which buttons and stylesheets we want to use on each instance of the editor.
An editor can be used again and again, with different configurations, and that is what we will be working on now.
To add a Data Type configuration field when using our Suggestion Property Editor, open the umbraco-package.json
file. Inside the meta
object, we can add the settings
object, which has the optional objects properties
and defaultData
.
Add some properties
:
In the section above, we added three configuration fields. Each entry in the properties
collection represents a Configuration field. It contains the necessary information for that field.
The field labeled "Disabled
" uses the Toggle Property Editor UI. This enables to switch the suggestion button on or off and provides the user with a toggle button.
The field labeled "Placeholder text
" uses the TextBox Property Editor UI, allowing the user to write a text.
The field labeled "Max characters allowed
" uses the Integer Property Editor UI, enabling the user to enter a numeric value.
The Property Editor UI needs to be declared as it declares what User Interface should be used for this field.
You can use any Property Editor UI to define Configuration fields. The alias of a given Property Editor UI can be found in Data Type configurations using that Property Editor.
We can now also set some default data on our new configurations:
Save the files and reload the backoffice. We can now configure our Data Type:
The next step is to gain access to our new configuration options. For this, open the suggestions-property-editor-ui.element.ts
file.
Create some state variables that can store our configurations:
Let's create a config property. Add a new import and add the following property:
Look up the alias of the config and then grab the value by said alias:
We can now use the configurations. Let's use the placeholder
and maxChars
for the input field and the disabled
option for the suggestion button.
Add a new import ifDefined
:
Update the render method:
Run the command npm run build
in the suggestions
folder.
Run the project.
Go to the Content section of the Backoffice to see the new changes in the property editor:
We have now added some configurations to our data type and used them in our Property Editor.
In the next step, we are going to integrate context with our Property Editor.
An overview of the default Property Editor Schema aliases
In the following section, you will find a list of the default Property Editor Schema aliases in Umbraco. We recommend you use one of these as propertyEditorSchemaAlias
when defining a custom Property Editor in umbraco-package.json
.
The chosen Property Editor Schema determines the resulting .NET runtime type of the stored Property Editor data. As this will ultimately be used when rendering the website, it is important to choose an appropriate Property Editor Schema.
Property Editor Schema alias | .NET runtime type |
---|---|
You can perform custom conversion of the stored Property Editor data by implementing your own Property Value Converter. In this case, the chosen Property Editor Schema determines the input data for the custom conversion.
Umbraco.Plain.DateTime
System.DateTime
Umbraco.Plain.Decimal
System.Decimal
Umbraco.Plain.Integer
System.Int32
Umbraco.Plain.Json
System.Text.Json.JsonDocument
Umbraco.Plain.String
System.String
Umbraco.Plain.Time
System.TimeSpan