Data List is a property-editor that takes a data source and makes the values selectable in a list editor control.
If that sounds too generic, think of it like this... take a data source, say a SQL query, and display the results in an editor, say a dropdown-list, or checkbox-list, or whatever!
This property-editor has taken some inspiration from the community package, nuPickers by Hendy Racher, (itself inspired by a uComponents idea). Please note, Data List is not a drop in replacement for nuPickers. Data List does not offer like-for-like features.
In your new Data Type, selected the "[Contentment] Data List" option. You will see the following configuration fields.
The two main fields are "Data source" and "List editor".
Selecting the Data source, you will be presented with a selection of data sources, including .NET enumeration, file system, Umbraco content, SQL, CSV, JSON and XML data.
An extensive list of all the built-in data-sources is available.
For our example, let's choose File System. You will then be presented with configuration options for this data source.
Once you have configured the data source, press the Done button at the bottom of the overlay.
Next is to select and configure the List editor. You will be presented with a selection of configuration options.
For our example, let's choose Checkbox List. You will then be able to configure the editor options.
Once you have configured both the Data source and List editor you can Save the Data Type and add it to your Document Type.
Once you have added the configured Data Type on your Document Type, the Data List will be displayed on the content page's property panel.
The beauty of the Data List property-editor is that all of the list editors are hot-swappable. Meaning that if you wanted to use a Radiobutton List instead, no problem.
or a Dropdown List?
or an Item Picker? (This list editor is visually similar to Umbraco's Content Picker editor.)
You can extend Data List with your own custom data sources and list editors.
For creating your own custom data source, you will need to create a new C# class that implements the Umbraco.Community.Contentment.DataEditors.IDataListSource
interface.
This interface contains one method called GetItems(config)
, which must return a IEnumerable<DataListItem>
object type.
The DataListItem
model is made up of four string
properties: Name
, Value
, Description
(optional) and Icon
(optional).
Here's an example of a custom data source of time zones, (leveraging .NET Framework's System.TimeZoneInfo
API).
public class TimeZoneDataSource : IDataListSource
{
public string Name => "Time zones";
public string Description => "Data source for all the time zones.";
public string Icon => "icon-globe";
public OverlaySize OverlaySize => OverlaySize.Small;
public Dictionary<string, object> DefaultValues => default;
public IEnumerable<ConfigurationField> Fields => default;
public IEnumerable<DataListItem> GetItems(Dictionary<string, object> config)
{
var items = new List<DataListItem>();
foreach (var timezone in TimeZoneInfo.GetSystemTimeZones())
{
items.Add(new DataListItem
{
Name = timezone.DisplayName,
Value = timezone.Id
});
}
return items;
}
}
If you require extra configuration options on your custom data source, this can be done by adding properties on the Fields
property. A property is defined using Umbraco's ConfigurationField
model.
public IEnumerable<ConfigurationField> Fields => new ConfigurationField[]
{
new ConfigurationField
{
Key = "alias",
Name = "Label (name)",
Description = "[Add a friendly description]",
View = "textstring"
}
}
As explained in the How to get the value? section, the values from your data source will be either string
or IEnumerable<string>
by default.
If you need something more than this, your custom data source should implement the Umbraco.Community.Contentment.DataEditors.IDataListSourceValueConverter
interface instead of IDataListSource
. This interface inherits from IDataListSource
, but also specifies two new methods that your data source will have to implement - that is the GetValueType
and ConvertValue
methods.
With this interface, the TimeZoneDataSource
class from before could now look like:
public class TimeZoneDataSource : IDataListSource, IDataListSourceValueConverter
{
public string Name => "Time zones";
public string Description => "Data source for all the time zones.";
public string Icon => "icon-globe";
public OverlaySize OverlaySize => OverlaySize.Small;
public Dictionary<string, object> DefaultValues => default;
public IEnumerable<ConfigurationField> Fields => default;
public IEnumerable<DataListItem> GetItems(Dictionary<string, object> config)
{
var items = new List<DataListItem>();
foreach (var timezone in TimeZoneInfo.GetSystemTimeZones())
{
items.Add(new DataListItem
{
Name = timezone.DisplayName,
Value = timezone.Id
});
}
return items;
}
public Type GetValueType(Dictionary<string, object> config)
{
return typeof(TimeZoneInfo);
}
public object ConvertValue(Type type, string value)
{
return TimeZoneInfo.FindSystemTimeZoneById(value);
}
}
This ensures that you'll get the value as IEnumerable<TimeZoneInfo>
instead of IEnumerable<string>
.
For creating your own custom list editor, you will need to create a new C# class that implements the Umbraco.Community.Contentment.DataEditors.IDataListEditor
interface.
This interface contains two properties, View
and DefaultConfig
(optional), and one method HasMultipleValues(config)
returning a boolean value for whether the list editor can select multiple or single values.
The View
property should set the path of the AngularJS view file. This can be whatever you want it to be. The only requirement is that the AngularJS controller (for the view) will be passed the data source items, (an object array - a serialization of the DataListItem
model), accessible by $scope.model.config.items
.
It is worth noting that both the IDataListSource
and IDataListEditor
types support Umbraco's approach for injecting dependencies. You can use any registered services, factories, helpers by adding them to the class constructor of your custom data-source/list-editor.
For an example, you can see how this is done with the UmbracoContentDataListSource
data-source.
The value for the Data List will either be a single value (string
) or multiple values (IEnumerable<string>
), (depending on how the list-editor implements the HasMultipleValues(config)
method).
To use this in your view templates, here are some examples.
For our example, we'll assume that your property's alias is "dataList"
, then...
Using Umbraco's Models Builder...
<ul>
@foreach (var item in Model.DataList)
{
<li>@item</li>
}
</ul>
Without ModelsBuilder...
The weakly-typed API may give you some headaches, we suggest using strongly-typed, (or preferably Models Builder).
Here's an example of strongly-typed...
<ul>
@foreach (var item in Model.Value<IEnumerable<string>>("dataList"))
{
<li>@item</li>
}
</ul>
Inspiration for how a Data List could be used...
Say you wanted to specify a business's opening days.
You could use the System.DayOfWeek
enum with a checkbox list to display the days of the week.
For the Data source, select .NET Enumeration. For the Enumeration type, select "mscorlib", then select "Day Of Week" option.
For the List editor, select the Checkbox List option.
Say you wanted to select from a list of countries. You could use a third-party XML data source.
For the Data source, select XML Data.
- For the URL, enter "https://www.madskristensen.net/posts/files/countries.xml"
- For the Items XPath, enter "/countries/country"
- For the Name XPath, enter "text()"
- For the Value XPath, enter "@code"
For the List editor, select Item Picker, maybe configure it with a nice Globe icon in blue?)
If you are interesting in real-world usage of Data List, here are some articles for further inspiration...
- Content Editor defined dropdowns/checkboxlists and radiobuttonlists in Umbraco v8 with Contentment - a post by Tim Geyssens.
- Umbraco Image Crop Picker using Contentment Data List - a post by Lee Kelleher (me).
- Creating an Author Picker Using Contentment - Paul Seal's article for Skrift magazine, June 2021.