Introducing Generic Fields

Published: 2018-03-12 in Piranha CMS by Håkan Edling

In 4.3 we will release the new SelectField which you can use to turn an Enum into a dropdown list in the manager interface. With this we also release support for creating Generic fields which is quite an exiting feature for those who want to create advanced custom fields. Let's first take a look at how the upcoming SelectField works.

Example usage

Let's say we want to create a Hero region which will display an image, a title and a description, but depending on the disposition of the image we want to position the text differently. With the new field this setup could look like:

public enum TextPosition
{
    [Display(Description = "Position text to the left")]
    Left,
    [Display(Description = "Position text to the right")]
    Right,
    [Display(Description = "Position text at the bottom")]
    Bottom
}

public class HeroRegion
{
    [Field]
    public StringField Title { get; set; }

    [Field]
    public TextField Description { get; set; }

    [Field]
    public ImageField Image { get; set; }

    [Field(Title = "Text Position")]
    public SelectField<TextPosition> TextPosition { get; set; }
}

public class MyPage : Page<MyPage>
{
    [Region]
    public HeroRegion Hero { get; set; }

    ...
}

Registering the select

In order to use a generic field each usage of it has to be registered so Piranha knows it should use it. For the Select Field you do this by calling the shorthand RegisterSelect<T> with the enum types you want to use in your Startup.cs. In this case it will look like this:

App.Fields.RegisterSelect<TextPosition>();

This will register the field and a serializer for it that only stores that selected enum in the database.

Editing the page

When editing the page in the manager it will look like this:

Manager UI

As you can see the descriptions added in the DisplayAttribute is shown in the drop down. If there's no attribute on the enum the default string representation of the enum is shown.

Can I create my own generic field?

Of course you can! As usual there's nothing hardcoded in Piranha to handle the new SelectField. However there's a few steps that needs to by followed to make it work.

1. Create a base class

Your generic field must have a non-generic base class. This type will be used when resolving the name of the EditorTemplate. For example:

public abstract class MyCoolFieldBase : Piranha.Extend.IField
{
    ...
}

[Field(Name = "Cool")]
public class MyCoolField<T> : MyCoolFieldBase
{
    ...
}

2. Create an EditorTemplate

Next up is creating the EditorTemplate that should render the field. The template should be located in:

~/Areas/Manager/Views/Shared/EditorTemplates/

The name should be the same as the base class of your generic field, in this example it would be MyCoolFieldBase.cshtml.

@model MyNamespace.MyCoolFieldBase

<div>Some HTML code here</div>

3. Register each usage in your Startup

Remember to register the field for every type you intend to use it with, for example:

App.Fields.Register<MyCoolField<TypeA>>();
App.Fields.Register<MyCoolField<TypeB>>();

4. Enjoy!

That's basically it. Stay tuned for the official release of 4.3, but if you want to try the functionality right away it is available in the master branch at the GitHub repo.