I don't think the SelectOne property was designed to be used like that. If the list of items is finite, have you considered just using the SelectMany attribute on a string property instead? It will end up as a comma separated list that you could convert into a list at consumption time.
[SelectMany(SelectionFactoryType = typeof(CountrySelectionFactory))]
public virtual string? Countries { get; set; }
[ScaffoldColumn(false)]
public IList<string>? SelectedCountries => Countries?.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)?.ToList();
Didn't find an easy fix, but I got it to work with a custom editor based on CheckBoxListEditor as that one seemed to work pretty much out of the box when using SelectMany on an IList<string> property:
Not saying it's the way to go, but here's the quick-and-dirty editor I used to get the job done:
define([
"dojo/_base/array",
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/on",
"dijit/form/Select",
"epi-cms/contentediting/editors/CheckBoxListEditor"
], function (
array,
declare,
lang,
on,
Select,
CheckBoxListEditor
) {
return declare([CheckBoxListEditor], {
buildRendering: function () {
this.inherited(arguments);
// Create a dropdown for the values passed from the selection factory
const select = new Select({
name: "string-select",
options: array.map(this.selections, (item) => {
return { label: item.text, value: item.value, selected: item.value === this.value }
})
}).placeAt(this.domNode);
// Update property value when dropdown value changes
this.own(
on(select, "change", lang.hitch(this, function (newValue) {
this._set("value", newValue);
this.onChange(this.value);
}))
);
},
_addCheckBoxForItem: function () {
// Do nothing, we add a Select instead of checkboxes
}
});
});
And here's the editor descriptor:
public class CountriesEditorDescriptor : EditorDescriptor
{
public const string UIHint = "Countries";
public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
{
base.ModifyMetadata(metadata, attributes);
metadata.EditorConfiguration["valueIsCsv"] = false;
metadata.ClientEditingClass = "my-site/StringListSelectionEditor";
metadata.SelectionFactoryType = typeof(CountrySelectionFactory);
}
}
Hi Ted,
You could achieve this without doing the dojo bit and using a generic list:
[EditorDescriptor(EditorDescriptorType = typeof(CollectionEditorDescriptor<CustomCountries>))]
public virtual IList<Countries> Countries { get; set; }
}
public class Countries
{
[Display(
GroupName = GroupNames.Content,
Order = 10)]
[SelectOne(SelectionFactoryType = typeof(CountriesSelectionFactory))]
public virtual string Country { get; set; }
}
[PropertyDefinitionTypePlugIn]
public class CountriesProperty : PropertyList<CustomCountries> { }
Thanks
Paul
Hi!
Is anyone aware of a limitation in using a SelectOne attribute with an IList<string> property?
The property looks like this:
The idea is to allow the editor to add an arbitrary number of strings, but each string should be selected from the dropdown.
Whenever I click "+" to add a value, I get just an empty space where the textbox would otherwise be:
If I add a string without the SelectOne attribute, and then later add the attribute, the dropdown shows up as expected:
However, if I click "+" to add another value, there's no dropdown (and no textbox) and I get a rather generic Dojo error in the console. 🤔
Edit: I realize this isn't exactly aligned with the original idea behind the SelectOne attribute, but I would think this requirement makes sense?
It makes more sense than trying to apply a SelectionEditor (i.e. dropdown) to the entire property?
I guess what I'm looking for is how to change the editor for each item in the IList<T> property, without having to roll my own.