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:
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:
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.