---
title: Register a custom editor
slug: cms-13/docs/register-a-custom-editor
docTags: 
createdAt: 2026-07-30T20:22:09.640Z
---

Register a custom editor to control how content authors interact with a specific property type in Optimizely CMS. A custom editor associates a Dojo widget with a .NET type and `UIHint`, connecting the server-side property model to the client-side editing experience. Use a custom editor when the built-in property editors do not support the input format a content type requires.

Before you start, confirm you have an Optimizely CMS project with the `EPiServer.CMS.UI` NuGet package installed and a basic understanding of Dojo widget development. For background on Dojo editors, see [Create an editor widget](docId\:cTLPxl9dUrsp9xLAX8FhU).

## Register an editor descriptor

The `EditorDescriptorRegistration` attribute maps a .NET type to a client-side editor class. The following example registers a custom `StringList` editor for `String[]` properties:

```csharp
[EditorDescriptorRegistration(TargetType = typeof (String[]), UIHint = Global.SiteUIHints.Strings)]
public class StringListEditorDescriptor: EditorDescriptor {
  public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes) {
    ClientEditingClass = "alloy/editors/StringList";
    base.ModifyMetadata(metadata, attributes);
  }
}
```

## Pass server-side data to the client editor

The `metadata.EditorConfiguration` dictionary passes data from the server to the client-side editor widget constructor as a JSON object.

The following example passes a server-created string array to the `StringList` editor:

```csharp
[EditorDescriptorRegistration(TargetType = typeof (String[]), UIHint = Global.SiteUIHints.Strings)]
public class StringListEditorDescriptor: EditorDescriptor {
  public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes) {
    base.ModifyMetadata(metadata, attributes);
    var reservedWords = new [] {
      "foo",
      "bar",
      "foobar"
    };
    //This array will be converted to a JSON object and passed to the constructor of the editor widget.        
    metadata.EditorConfiguration.Add("reservedWords", reservedWords);
  }
}
```

## Configure different settings for forms and on-page editing

Specify separate editor configurations for forms editing and on-page editing (OPE). Set the default editor in the constructor for forms editing. Override the on-page editor with `metadata.CustomEditorSettings`.

The following example configures a `float` editor with different behavior for each mode:

```csharp
[EditorDescriptorRegistration(TargetType = typeof (float))]
public class FloatNumberEditorDescriptor: EditorDescriptor {
  public FloatNumberEditorDescriptor() {
    //The default editing class that will be used in forms editing mode.
    ClientEditingClass = "dijit/form/NumberTextBox";
  }

  public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes) {
    base.ModifyMetadata(metadata, attributes);

    if (!attributes.OfType<RangeAttribute>().Any()) {
      var constraints = new Dictionary<string,object>() {
          {
            "min",
            Double.MinValue
          }, {
            "max",
            Double.MaxValue
          }
        };
      //These settings will be passed to the constructor of the editor widget.
      metadata.EditorConfiguration.Add("constraints", constraints);
    }

    //Define what kind of editor we want to have, in this case we want to create an inline editor. This is used
    //when the user is in OPE ("on page editing") mode.
    metadata.CustomEditorSettings["uiWrapperType"] = UiWrapperType.ContentEditable;
    //Specify the class for a custom editor responsible for the actual editing in OPE.
    //If not defined the default (forms) editor will be used.
    metadata.CustomEditorSettings["uiType"] = "dijit/form/NumberTextBox";
  }
}
```

A complete custom Dojo editor example is available in the [Alloy sample site](https://github.com/episerver/alloy-mvc-template).
