Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Guide on how to work with and create Property Editors in Umbraco
This tutorial contains step-by-step instructions for building a custom Property editor.
The Property Editor articles are a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
This section describes how to work with and create Property Editors. A property editor is the editor used to insert content into Umbraco. See here for definition
A property editor is an editor used to insert content into Umbraco. A Property Editor is composed of two extensions: Property Editor Schema and Property Editor UI.
Reference for the package.manifest JSON file format to register one or more property editors for Umbraco.
Convert the stored property data value to a useful object returned by the Published Content APIs.
Use Property Actions to add additional functionaility to your custom property editors.
Learn how to build your own Block Editors.
Learn how to extend Property editors to track entity references inside the property editor.
This section describes how to work with and create Property Editors.
This page is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
A property editor is an editor used to insert content into Umbraco. A Property Editor is composed of two extensions. To form a full Property Editor you will need a:
A Property Editor UI is utilizing a Property Editor Schema, and you can have multiple Property Editor UIs for one Schema. This means you can find a Schema that solves your needs. You only need to build a Property Editor UI.
Each Property Editor can have multiple Property Editor UIs.
Both a Property Editor Schema and Property Editor UI can define the Settings used for their configuration.
Data Type Settings for a Property Editor or Property Editor UI is defined in the manifests.
They both use the same format for their settings.
The Server side part of a Property Editor
This page is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
The Property Editor Schema is server code, written in C#. This handles the storage of a Property Editor and defines Server Side Validation and Property Value Converters.
The Property Editor Schema settings are used for configuration that the server needs to know about.
Manifest
Presenting the Editing Experience of a Property Editor
This page is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
The Property Editor UI is the UI that is used to edit the data in the backoffice.
The Property Editor UI is a pure front-end extension. This determines how the data of a Property Editor is presented and manipulated. The Extension points to a Web Component.
If no Property Editor Schema is specified in the manifest, the Property Editor UI cannot be used for Content Types. However, it can still be utilized to manipulate JSON. A case of that could be a Settings property for another Property Editor UI or Schema.
The Property Editor UI settings are used for configuration that is related to rendering the UI in the backoffice. This is the same for Property Editor Schemas:
The Property Editor UI inherits the Settings of its Property Editor Schema.
Manifest
Inherit the interface, to secure your Element live up to the requirements of this.
Example with LitElement
A guide to creating a custom property value converter in Umbraco
A Property Value Converter converts a property editor's database-stored value to another type. The converted value can be accessed from MVC Razor or any other Published Content API.
Published property values have four "Values":
Source - The raw data stored in the database, this is generally a String
Intermediate - An object of a type that is appropriate to the property, for example a nodeId should be an Int
or a collection of nodeIds would be an integer array, Int[]
Object - The object to be used when accessing the property using a Published Content API, for example UmbracoHelper's GetPropertyValue<T>
method
PropertyValueConverters are automatically registered when implementing the interface. Any given PropertyEditor can only utilize a single PropertyValueConverter.
If you are implementing a PropertyValueConverter for a PropertyEditor that doesn't already have one, creating the PropertyValueConverter will automatically enable it. No further actions are needed.
If you aim to override an existing PropertyValueConverter, possibly from Umbraco or a package, additional steps are necessary. Deregister the existing one to prevent conflicts in this scenario.
The built-in PropertyValueConverters included with Umbraco, are currently marked as internal. This means you will not be able to remove them by type since the type isn't accessible outside of the namespace. In order to remove such PropertyValueConverters, you will need to look up the instance by name and then deregister it by the instance. This could be the case for other PropertyValueConverters included by packages as well, depending on the implementation details.
Implement IPropertyValueConverter
from the Umbraco.Cms.Core.PropertyEditors
namespace on your class
This method is called for each PublishedPropertyType (Document Type Property) at application startup. By returning True
your value converter will be registered for that property type and your conversion methods will be executed whenever that value is requested.
Example: Checking if the IPublishedPropertyType EditorAlias property is equal to the alias of the core content editor. This check is a string comparison but we recommend creating a constant for it to avoid spelling errors:
This method is called to determine if the passed-in value is a value, and is of the level specified. There's a basic implementation of this in PropertyValueConverterBase
.
This is where you can specify the type returned by this Converter. This type will be used by ModelsBuilder to return data from properties using this Converter in the proper type.
Example: Content Picker data is being converted to IPublishedContent
.
Here you specify which level the property value is cached at.
A property value can be cached at the following levels:
PropertyCacheLevel.Unknown
Do not use this cache level unless you know exactly what you're doing. We recommend using the PropertyCacheLevel.Element
level.
PropertyCacheLevel.Element
The property value will be cached until its element is modified. The element is what holds (or owns) the property. For example:
For properties used at the page level, the element is the entire page.
For properties contained within Block List items, the element is the individual Block List item.
This is the most commonly used cache level and should be your default, unless you have specific reasons to do otherwise.
PropertyCacheLevel.Elements
The property value will be cached until any element (see above) is changed. This means that any change to any page will clear the property value cache.
This is particularly useful for property values that contain references to other content or elements. For example, this cache level is utilized by the Content Picker to clear its property values from the cache upon content updates.
PropertyCacheLevel.Snapshot
The property value will only be cached for the duration of the current snapshot.
A snapshot represents a point in time. For example, a snapshot is created for every content request from the frontend. When accessing a property in a snapshot using this cache level, it gets converted, cached throughout the snapshot, and later cleared.
For all intents and purposes, think of this cache level as "per request". If your property value should only be cached per request, this is the cache level you should use. Use it with caution, as the added property conversions incur a performance penalty.
PropertyCacheLevel.None
The property value will never be cached. Every time a property value is accessed (even within the same snapshot) property conversion is performed explicitly.
Use this cache level with extreme caution, as it incurs a massive performance penalty.
There are a few different levels of conversion which can occur.
This method should convert the raw data value into an appropriate type. For example, a node identifier stored as a String
should be converted to an Int
or Udi
.
Include a using Umbraco.Extensions;
to be able to use the TryConvertTo
extension method.
This method converts the Intermediate to an Object. The returned value is used by the GetPropertyValue<T>
method of IPublishedContent
.
The below example converts the nodeId (converted to Int
or Udi
by ConvertSourceToIntermediate) into an 'IPublishedContent' object.
Content Picker to IPublishedContent
using IPropertyValueConverter
interface
Guide on how to implement Property Actions for Property Editors in Umbraco
This page is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
Property Actions are a built-in feature that provide a generic place for secondary functionality for property editors.
Property Actions appear as a small button next to the label of the property, which expands to show the available actions. They are defined and implemented in the Property Editor, making it open as to what a Property Action is.
Property Actions are an array of objects defining each action. An action is defined by the following properties:
isDisabled
is used to disable an Action, which change the visual appearance and prevents interaction. Use this option when an action wouldn't provide any change. In the example above, the action remove all entries
would not have any impact if there is no entries.
The implementation of Property Actions varies depending on whether your Property Editor is implemented with a Controller or as a Component.
When your Property Editor is implemented with a Controller, use the following approach for the Property Action:
Follow this guide if your Property Editor is implemented as a Component. The Component must be configured to retrieve an optional reference to umbProperty
. The requirement must be optional because property-editors are implemented in scenarios where it's not presented.
See the following example:
See the following example for implementation of Property Actions in a Component, notice the difference is that we are parsing actions to this.umbProperty.setPropertyActions(...)
.
Property Editors can be used and implemented anywhere in the Umbraco Backoffice.
The simplest way to integrate one or more Property Editors is done using two Components: the Property Dataset component and a Property component.
The umb-property
component renders a property using a Property Editor UI.
The umb-property-dataset
component provides the dataset for any properties within. It holds the data even if the actual property is not rendered. This makes it possible to hide properties in tabs or other ways.
In the following example a dataset is implemented with two properties:
Notice how the values of the properties are handled by the dataset, leaving you with one component to integrate.
Guide on how to implement tracking entity references for Property Editors in Umbraco
Property editors can be extended further to track entity references that may be selected or referenced inside the property editor. For example in the core of the CMS we have added this to numerous property editors.
A good example of this is the Media Picker. The CMS stores a reference to the selected media item, enabling the identification of content nodes that use that particular media item. This avoids it being accidentally deleted if it is being used.
When a content node is saved it will save the entity references as relations.
Go to the Media section.
Select a media item and click the Info tab.
Go to the Settings section.
Under the Relations from the Advanced section, select Related Document relations.
Go to the Settings section.
Expand the Data Types folder.
Select the Data Type you wish to view the references.
Navigate to the Info tab.
The following example shows how to implement tracking for the inbuilt CMS property editor Content Picker. It will always add a specific media reference, regardless of what value is picked in the content picker. In your own implementations, you will need to parse the value stored from the property editor you are implementing. You will also need to find any references to picked items in order to track their references.
You'll need a Composer to enable the tracking example:
This page is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
In order for your editor to become a Block Editor, you must first declare it using C#:
It is, however, recommended to declare your own Block Editors in C#. As you will see in the following, the property editor alias ("MyOwn.UnicornBlocksEditor"
) will be part of the data structure. For any eventual future extensibility, it is good to have the correct alias in the content structure from the beginning.
The Block Editor data structure consists of three main parts:
Layout: The Layout defines Blocks that each will reference (by UDI) a content item in the list of data. The Layout object pairs keys with Property Editor aliases and their value type varies based on setup.
ContentData: A list of content items based on ElementTypes (IPublishedElement).
SettingsData: A list of content items based on ElementTypes (IPublishedElement).
In the following example the layout object "MyOwn.UnicornBlocksEditor" is of type Array.
We created the BlockEditorModelObject to aid in managing the presented Data Structure in the Block Editor.
To get a better understanding of what the Model Object does for you, we need to look at some usages of the Model Object.
The layout
of a Block Editor can be any structure. Therefore the Model Object (BlockEditorModelObject) cannot maintain this data. Our usage of the Model Object becomes complex. We give it a reference to a layout
entry and perform an action that may need to reflect changes back to the layout
.
Since the origin of blocks is in the layout
the Model Object only can serve as a helper to maintain and create data. Therefore the Property Editor code will be using the layout
as origin, using the Model Object to help manage specific parts.
This is explained in more detail below.
Instantiate a Model Object and load dependencies. Provide the basic structure for the layout
property when receiving the reference to it:
Use the Model Object to create a Block and append the returned layout-entry to the layout
.
In the following example we will create a new block and append it at the appropriate location in the 'layout' object:
The layout-entries alone do not provide much value when displaying or editing Blocks.
Our Model Object allows obtaining a Block Object by parsing a block's layout-entry for a specific Block.
The Block Object provides data of interest. The most important of these properties are: Block configuration, a label and the Block content in the Element Type Data Model format. This Content-model is useful for building the UI for editing the Content of a Block.
This example uses the Model Object to retrive a Block Object for outputting its label in the console.
This similar example uses the Block Object for setting a value on the first property in the Blocks Content.
Removing a Block and destroying its data is done by calling the removeDataAndDestroyModel
method of the Model Object, which allows us to maintain the 'layout' object.
Your code will be based on working with Block Objects and therefore removal of a Block is be done by referring to a Block Object.
This example shows how to remove the first Block of our imaginary Block Editor and remove the block from our layout.
Block Objects are used extensively and should be available throughout your Block Editor's runtime, rather than created for each action.
You probably want to use BlockObjects for your property-editor view. We append them to layout entries, so you can access them as properties from the layout object.
The following example loops through a layout array to display the contentUdi of each block:
We use labelKey
and labelTokens
to retrieve a localized string that is displayed as the Actions label.
Before reading this document we highly recommend that you familiarise yourself with .
It is not strictly necessary to define your own property editor in C#. As outlined in the article, all Umbraco core property editors can be reused.
The code sample above inherits all functionality from Block List and adds no new functionality. If this is sufficient, you can use the Block List property editor alias "Umbraco.BlockList"
as Property Editor Schema in your .
A Property Dataset is a Context API that holds the data for a set of properties.
The umb-property-dataset
component provides a Property Dataset Context for any properties within. This provides a way to implement such purely via Elements.
In the following example a dataset is implemented by using the umb-property-dataset
component together with with two umb-property
components: