Join us this Friday for AI in Action at the Virtual Happy Hour! This free virtual event is open to all—enroll now on Academy and don’t miss out.
Join us this Friday for AI in Action at the Virtual Happy Hour! This free virtual event is open to all—enroll now on Academy and don’t miss out.
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.