Welcome Guest, you are in: Login

Umbraco v5 Wiki

RSS RSS

Navigation





Search the wiki
»

PoweredBy

Developing Property Editors

RSS
Modified on 2011/04/06 01:41 by Shannon Deminick Categorized as Uncategorized
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:

  • Id
  • Name
  • Alias

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:

  1. Create a new .cshtml file in your Property Editor's View folder.
  2. Add an @inherits declaration (@model declarations will not work with embedded views). Example: @inherits WebViewPage<Umbraco.CMS.Web.PropertyEditors.RichTextBox.RichTextEditorModel>
  3. 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;
  4. Create the rest of your view as per normal

Embedding a Property Editor view

  1. Right click your .cshtml view, select properties and change the 'Build Action' to 'Embedded Resource'
  2. 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

  1. In your class library, create a new folder for your property editor with an appropriate name (i.e. RichTextBox )
  2. Create 2 subfolders named: Resources and Views (see best practices guide above)
  3. Create a new property editor class and inherit from Umbraco.CMS.Web.PropertyEditors.PropertyEditor
  4. Add the Umbraco.CMS.Web.PropertyEditors.PropertyEditorAttribute attribute to the class and fill in it's details: 'id', 'alias' and 'name'
    • IMPORTANT: For the 'id' you will need to generate your own GUID, make sure that you haven't copied and pasted this GUID from other code!
    • EXAMPLE:
      [PropertyEditorAttribute("3F5ED845-7018-4BDE-AB4E-C7106EE0992D", "TextBox", "Text Box")]
  5. 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
  6. 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.

  1. Create a class that inherits from Umbraco.CMS.Web.PropertyEditors.PreValueModel
  2. Implement both required constructors, 1st accepting zero arguments, 2nd accepting a string as an argument (i.e. string preValues )
  3. 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
  4. 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.

  1. 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.
  2. 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 embed

Step by step guide for embedding assets for Property Editors

  1. Create a 'Resources' folder next to your Property Editor classes
  2. Add your assets to the 'Resources' folder
  3. Highlight all of these assets (Shift or Ctl + click), right click and select 'Properties'
  4. In the 'Build Action' on the properties pane, select 'Embedded Resource'
  5. 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")]
  6. Change the paths of your CSS images to use the PerformSubstitution syntax which allows you to reference embedded images in you stylesheet.
    • EXAMPLE:
      background: url('<%= WebResource("Umbraco.CMS.Web.PropertyEditors.TextBox.Resources.bold.png")%>') no-repeat left top;
    • Note the <%= WebResource("...") %> syntax which allows you to reference a fully qualified path of an embedded image
  7. 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)

ScrewTurn Wiki version 3.0.4.560. Some of the icons created by FamFamFam.