This page is a Draft, its content is not complete and might contain errors.
Definitions
A
Property Editor is the editor that a
Data Type references. In Umbraco versions previous to version 5, there was no official name given to the editor that a Data Type referenced and it was also known as a Data Type. In version 5 we differentiate between the 2 aspects of Umbraco. A Data Type is defined by the Administrator of Umbraco which references a Property Editor. A Property Editor on the other hand is defined by a developer and compiled into a DLL.
Property Editors consist of two editors:
Content Editor
The
Content Editor is the control/form that an Umbraco back-office content editor uses to edit the data. An example is the TinyMCE rich text editor, or the Multi-node tree picker from uComponents.
Pre Value Editor
The
Pre Value Editor is the control/form that is displayed to an Umbraco back-office administrator when viewing the definition of a
Data Type. The
Pre Value Editor gives the administrator the control to customize the
Data Type either by functionality of by 'look and feel'. An example is enabling/disabling certain controls of the rich text editor such as 'Bold' or 'Italic'.
Classes overview
There are three classes which need to be implemented to make up the Property Editor type in Jupiter:
PropertyEditor
This is the core class which defines the Property Editor, it contains the base information for a Property Editor:
This data is actually populated from the
PropertyEditorAttribute which is required on a custom Property Editor.
When creating a Property Editor you need to implement these two methods:
public abstract EditorModel CreateEditorModel(string preValues);
public abstract PreValueModel CreatePreValueEditorModel(string preValues);
When you create a
PropertyEditor class you must decorate it with the
PropertyEditorAttribute, this attribute is where the Id (as a valid string GUID), Name and Alias are defined, allowing the Umbraco internals to find out information about the types without creating an instance of it
EditorModel & EditorModel<TPreValueModel>
The
EditorModel class is the class which the properties that a CMS editor will see, so properties added here will be exposed as something to edit.
To implement this class you need to implement two methods:
public abstract string GetSerializedValue();
public abstract void SetModelValues(string serializedVal);
These are the methods which will convert the editor model into something that can be stored by the persistence layer. These methods put the responsibility of converting the editor model into a string back on the developer, so that it can be ensured that Umbraco doesn't do anything funky to the data.
When creating a Property Editor with a custom
PreValueModel (see next section for overview) you need to inherit from the
EditorModel, and specify the type of the
PreValueModel as the generic argument.
This will allow the
PreValueModel to be exposed to the
EditorModel so that it can be interacted with (say, for validation purposes).
PreValueModel
This class is used to provide configuration settings for the Property Editor. This is what you would be presented with when you're creating or editing a
Data Type in the Umbraco Developer section.
To expose configuration settings you need to add properties to your implementation of this class.
Best practices
It is strongly advised to follow these best practices when creating Property Editors so that all Property Editors are consistent.
- Each Property Editor should exist in it's own folder/namespace
- The folder structure of a Property Editor in you class library should be:
Property Editor Name
- Resources
- Views
- The
Resources folder is where all of the embedded resources for this editor are stored (i.e. JavaScript, CSS files and images) - The
Views folder is where all of the embedded views for this editor are stored - Name your Property Editor so that the name is suffixed with the term '
Editor' (i.e. RichTextEditor) - Name your Property Editor Model so that the name is suffixed with the term '
EditorModel' (i.e. RichTextEditorModel) - Name your Property Editor Pre Value Model so that the name is suffixed with the term '
PreValueModel' (i.e. RichTextPreValueModel) - Embed the resources that your Property Editor requires (JavaScript, CSS & images)
- Do NOT embed resources that will definitely be used by other components, these can be stored on the file system
- Do NOT embed JavaScript libraries that will probably overlap with other developers' components
- All views for Property Editors should be embedded. NOTE: Currently there is no support for non-embedded property editor views but we will cater for this at some stage.
Creating & Embedding Views
The UI for Property Editors is either created by MVC scaffolding and/or created by Razor views which are currently required to be embedded into your assembly.
Embedded views can be attached to either a
Class or a
Property. If you attach an embedded view to a Class, then you will be creating the editor for the entire class and all of it's properties, otherwise you can attach an embedded view to a Property which will let MVC scaffolding do the work but will render our your custom view when it encounters your decorated property.
Creating a Property Editor view
Because of the nature of the Razor view engine and the Razor parser, embedded views cannot use the
@model declaration syntax and they must also explicitly declare the standard MVC imports statements... see below:
- Create a new
.cshtml file in your Property Editor's View folder. - Add an
@inherits declaration (@model declarations will not work with embedded views). Example: @inherits WebViewPage<Umbraco.CMS.Web.PropertyEditors.RichTextBox.RichTextEditorModel> - Add the following standard
@using statements:
@using System.Web.Helpers;
@using System.Web.Mvc;
@using System.Web.Mvc.Ajax;
@using System.Web.Mvc.Html;
@using System.Web.Routing;
@using System.Web.WebPages;
@using Microsoft.Web.Mvc;
@using ClientDependency.Core;
@using ClientDependency.Core.Mvc;
@using Umbraco.CMS.Web;
@using Umbraco.CMS.Web.Editors;
- Create the rest of your view as per normal
Embedding a Property Editor view
- Right click your
.cshtml view, select properties and change the 'Build Action' to 'Embedded Resource' - Decorate your class or property with the
EmbeddedView attribute using the fully qualified path of the embedded view resource and the assembly name that the view is embedded in. Example:
[EmbeddedView("Umbraco.CMS.Web.PropertyEditors.ComplexModelTest.Views.NestedObjectEditor.cshtml", "Umbraco.CMS.Web.PropertyEditors")]
public class ComplexModelTestEditorModel : EditorModel { .... }
Creating a Property Editor definition
- In your class library, create a new folder for your property editor with an appropriate name (i.e. RichTextBox )
- Create 2 subfolders named:
Resources and Views (see best practices guide above) - Create a new property editor class and inherit from
Umbraco.CMS.Web.PropertyEditors.PropertyEditor - Add the
Umbraco.CMS.Web.PropertyEditors.PropertyEditorAttribute attribute to the class and fill in it's details: 'id', 'alias' and 'name' - Implement the required (abstract) methods:
CreateEditorModel and CreatePreValueEditorModel- At this point of creating a Property Editor, you will have not defined an
EditorModel or a PreValueModel to return. Once you create these objects (see further down in the documentation) then you will need to return instances of these objects in this methods - If you don't need a pre value editor you can return an instance of
Umbraco.CMS.Web.PropertyEditors.BlankPreValueModel in your PreValueModel method
- Embed all of the resources that you require
Example
This is the TextBox Property Editor class:
[assembly: WebResource("Umbraco.CMS.Web.PropertyEditors.TextBox.Resources.TextBoxPropertyEditor.js", "application/x-javascript")]
[assembly: WebResource("Umbraco.CMS.Web.PropertyEditors.TextBox.Resources.TextBoxPropertyEditor.css", "text/css", PerformSubstitution = true)]
[assembly: WebResource("Umbraco.CMS.Web.PropertyEditors.TextBox.Resources.bold.png", "image/png")]
[assembly: WebResource("Umbraco.CMS.Web.PropertyEditors.TextBox.Resources.italic.png", "image/png")]
[assembly: WebResource("Umbraco.CMS.Web.PropertyEditors.TextBox.Resources.link.png", "image/png")]
[PropertyEditorAttribute("3F5ED845-7018-4BDE-AB4E-C7106EE0992D", "TextBox", "Text Box")]
public class TextBoxPropertyEditor : PropertyEditor
{
public override EditorModel CreateEditorModel(string preValues)
{
var preValueEditorModel = CreatePreValueEditorModel(preValues);
return new TextBoxEditorModel(preValueEditorModel as TextBoxPreValueModel);
}
public override PreValueModel CreatePreValueEditorModel(string preValues)
{
return new TextBoxPreValueModel(preValues);
}
}
Creating a Pre Value model & editor
As mentioned above, if you don't need a pre value editor you can return an instance of Umbraco.CMS.Web.PropertyEditors.BlankPreValueModel in your PreValueModel method.- Create a class that inherits from
Umbraco.CMS.Web.PropertyEditors.PreValueModel - Implement both required constructors, 1st accepting zero arguments, 2nd accepting a string as an argument (i.e.
string preValues ) - Add properties that you wish to persist for you pre-values. An example of this would be an 'Is Required' boolean property or a 'Regex validation statement' string property.
- Use DataAnnotations to change how this property is displayed to the Umbraco administrator. For Example the
DisplayName attribute will change the label text in the UI, or you can add validation to the form field by adding attributes such as Required attribute
- Add custom views either at the property level or at the class level by using the
Umbraco.CMS.Web.EmbeddedViewEngine.EmbeddedViewAttribute- NOTE: Currently, all views for Property Editors are required to be embedded. Eventually we will allow for views for Property Editors to exist on the file system.
Example
An example pre value editor model:
public class TextBoxPreValueModel : PreValueModel
{
public TextBoxPreValueModel()
: this(string.Empty)
{ }
public TextBoxPreValueModel(string preValues)
: base(preValues)
{ }
/// <summary>
/// The text box mode
/// </summary>
[EmbeddedView("Umbraco.CMS.Web.PropertyEditors.TextBox.PreValueModeEditor.cshtml", "Umbraco.CMS.Web.PropertyEditors")]
public TextBoxMode Mode { get; set; }
[AllowDocumentTypePropertyOverride]
[DisplayName("Required")]
public bool IsRequired { get; set; }
[AllowDocumentTypePropertyOverride]
[DisplayName("Regular expression validation statement")]
public string RegexValidationStatement { get; set; }
}
Creating an Editor model & editor
NOTE: Until data persistence is completed it will be required to override
SetModelValues and
GetSerializedValue. Once data persistence is complete the functionality of these two methods will hopefully be handled automatically.
- Create a class that inherits from either
Umbraco.CMS.Web.PropertyEditors.EditorModel or Umbraco.CMS.Web.PropertyEditors.EditorModel<TPreValueModel>- This depends on if you have a pre-value editor or not. If you don't have a pre value editor, then you can simply inherit from
Umbraco.CMS.Web.PropertyEditors.EditorModel, otherwise if you do then you need to inherit from Umbraco.CMS.Web.PropertyEditors.EditorModel<TPreValueModel> where TPreVaueModel is the pre value Type you previously created.
- Create a constructor for your class if it inherits from
Umbraco.CMS.Web.PropertyEditors.EditorModel<TPreValueModel> with an argument type of TPreValueModel- This constructor accepts the pre value model that you've defined which allows you to customize your editor based on the values specified by the Umbraco administrator
(NOT FINISHED DOCUMENTING!)
Embedding assets/resources
See Best Practices guide above for what assets to embedStep by step guide for embedding assets for Property Editors
- Create a 'Resources' folder next to your Property Editor classes
- Add your assets to the 'Resources' folder
- Highlight all of these assets (Shift or Ctl + click), right click and select 'Properties'
- In the 'Build Action' on the properties pane, select 'Embedded Resource'
- Mark each asset to be embedded in the assembly by using the assembly
WebResource attribute- You will need to fully qualified name of the asset
- Best practices stipulate that you should put the WebResource attributes in the same file that your Property Editor class is declared
- EXAMPLE JavaScript:
[assembly: WebResource("Umbraco.CMS.Web.PropertyEditors.TextBox.Resources.TextBoxPropertyEditor.js",
"application/x-javascript")] - When embedding CSS, ensure you specify
PerformSubstitution as this will allow you to use embedded images in your CSS!!!! - EXAMPLE CSS:
[assembly: WebResource("Umbraco.CMS.Web.PropertyEditors.TextBox.Resources.TextBoxPropertyEditor.css",
"text/css",
PerformSubstitution = true)] - EXAMPLE Image:
[assembly: WebResource("Umbraco.CMS.Web.PropertyEditors.TextBox.Resources.bold.png",
"image/png")]
- Change the paths of your CSS images to use the
PerformSubstitution syntax which allows you to reference embedded images in you stylesheet. - Make your Property Editor dependant on the embedded JavaScript and/or stylesheets using ClientDependency Html helper methods inside of your View(s):
RequiresJsResource and RequiresCssResource- EXAMPLE:
@{
Html
.RequiresJsResource(typeof(TextBoxPropertyEditor), "Umbraco.CMS.Web.PropertyEditors.TextBox.Resources.TextBoxPropertyEditor.js")
.RequiresCssResource(typeof(TextBoxPropertyEditor), "Umbraco.CMS.Web.PropertyEditors.TextBox.Resources.TextBoxPropertyEditor.css");
}
- Notice that you have to pass the type of your Property Editor, this is to tell the system which assembly the resources are embedded in. The type specified doesn't have to be that of your Property Editor, it just needs to be a type inside of your assembly that you are embedding the resources in, however as a best practice, use the type of your Property Editor
Custom Validation
(NOT FINISHED DOCUMENTING!)
Exposing Pre Values to Document Types
A new feature of Umbraco v5 is that we can 'bubble' Pre Value properties up to the Document Type Property editor. An example of this is the TextBox IsRequired and Regex validation fields. Currently in v4, these 2 properties are attached to every Document Type Property editor, however for many Data Type's these 2 properties don't make any sense so in v5 we're allowing Property Editors to define what kind of validation (or other customization properties) can be 'bubbled' up to the Document Type Property thus allowing administrators to customize a Data Type specifically to a Document Type Property without having to create multiple Data Types for each customization.
(HASN'T BEEN IMPLEMENTED YET... STAY TUNED)
Custom Model Binding
(HAS YET TO BE TESTED... STAY TUNED)
Custom Serialization
(DEPENDANT ON DATA PERSISTENCE... TO BE WRITTEN)