Custom EPiServer key value property with predefined keys support

I've created a custom property with support for predefined keys. You can check out the source code on GitHub and you can install it by simply running Install-Package JOS.PropertyKeyValueList in the Package manager console.

Before I started creating the property I did some googling and I found this blogpost by Peter Löfman where he had done something quite similar to what I wanted to achieve so I used his blog post to get started.

The property has two "modes", ReadOnlyKeys or Normal.

ReadOnlyKeys

Add the property like this to try it out.

[BackingType(typeof(PropertyKeyValueList))]
[KeyValue(typeof(ReadOnlyKeysProvider))]
public virtual IEnumerable<KeyValueItem> ReadOnly { get; set; }

ReadOnlyMode is specified by passing in an IReadOnlyKeysProvider to the constructor of the KeyValueAttribute.

IReadOnlyKeysProvider

public interface IReadOnlyKeysProvider
{
    List<string> GetKeys();
}

My implementation in this example looks like this:
ReadOnlyKeysProvider

public class ReadOnlyKeysProvider : IReadOnlyKeysProvider
{
    public List<string> GetKeys()
    {
        return new List<string>()
        {
            "Arsenal",
            "Real Madrid",
            "Barcelona",
            "Skara FC",
            "Axvalls IF",
            "Juventus",
            "IFK Göteborg",
            "Djurgårdens IF",
            "AIK"
        };
    }
}

When specifying a IReadOnlyKeysProvider the property will render in ReadOnlyKeysMode and look like this:
Property rendered in readOnlyKeysMode
The editor will only be able to edit the "value" portion of the property, not the predefined keys. It's not possible to add new items in this mode.

Normal

Add the property like this to try it out.

[BackingType(typeof(PropertyKeyValueList))]
[KeyValue]
public virtual IEnumerable<KeyValueItem> NotReadOnly { get; set; }

The property will look like this in edit mode:
Property rendered in normal mode
Currently it's possible to add as many items as you like but Im thinking of adding an optional MaxLimit.

Some notes

Im no DOJO expert but in all examples I've found online regarding custom EPiServer properties it looks like this.value should be available in the postCreate method. this.value is null for me in postCreate for some weird reason, but if I add the below code(wrapping it in a setTimeout block), it works? I've submitted a ticket to the developer support but if anyone have any idea of why it's null I would gladly accept your help :)

Ugly workaround for null value in postCreate

postCreate: function () {
    this.readOnlyKeysMode = this.readOnlyKeys !== undefined && this.readOnlyKeys.length > 0;
    //This is a really ugly fix for a (possible) episerver bug? 
    //this.value is null in postCreate but if we wait 200ms, this.value suddenly isn't null anymore...?
    var that = this;
    setTimeout(function () {
        if (that.readOnlyKeysMode) {
            domStyle.set(that.kvlAddButton, {
                "display": "none"
            });
            array.forEach(that.readOnlyKeys, that._renderReadOnlyMode, that);
        } else {
            array.forEach(that.value, that._renderNormalMode, that);
        }
    }, 200);
}

UPDATE
After consulting the support, Episerver changed some logic in a recent UI release, so instead of getting the value in postCreate, you can retrieve it in _setValueAttr. I will update my code asap to get rid of the ugly timeout.

Custom EPiServer key value property with predefined keys support
Share this