Custom Icons with an Enum-Based Data Picker

tagged with Backoffice Developer

Learn how we can use Contentment to provide any icon in a picker inside of Umbraco’s backoffice

If you haven't heard of Contentment before, it's a highly customizable package that enhances the editor-friendliness of the backoffice. It is developed by Lee Kelleher and you can find the source code here.

There are a bunch of features available:

  • Bytes - a read-only label to display file sizes in relative bytes.
  • Code Editor - a code snippet editor, (using the ACE library bundled with Umbraco).
  • Content Blocks - a block editor, configurable using element types.
  • Data List - an editor that combines a custom data source with a custom list editor.
  • Data Picker - advanced picker editor to query a custom data source.
  • Editor Notes - similar to Notes (below), with enhanced UI options.
  • Icon Picker - an editor to select an icon, (from the Umbraco icon library).
  • Notes - a label to display rich-text instructional messages for content editors.
  • Number Input - a numeric editor, with sizing configurations.
  • Render Macro - a label dynamically generated from an Umbraco Macro.
  • Social Links - an editor to manage links for social network platforms.
  • Templated Label - a display label, ideal for showing data from 3rd-party systems.
  • Textbox List - a multi-textstring editor, adds a textbox for each item in a data source.
  • Text Input - a textstring editor, configurable with HTML5 options.

In this article, we will dive deep into the concept of using a C# Enum inside our code to create a Data List with custom icons for the editor. We will explore how this can be achieved in a highly elegant and user-friendly manner.

Why would you want to use an enum, anyway?

Enums, also known as enumerations, are labels used to represent specific values in programming.

Imagine you have a set of choices, such as different colors or sizes, and you want to incorporate them into your code. Instead of using complicated numbers or confusing words, enums allow you to assign each choice a clear and user-friendly name.

For instance, you can utilize an enum to represent colors such as "Red," "Blue," and "Green," or sizes like "Small," "Medium," and "Large." This not only enhances the readability and comprehension of your code but also helps prevent errors by consistently utilizing these user-friendly names throughout your program.

Creating our super-charged icon picker

First of all, let’s create our custom enum - we’re going to use Fontawesome 5 icons inside of our solution to allow them be selected, for this all we need to do is create a regular enum and add one additional attribute


public enum IconVariant
{
    [Description("fak fa-active")]
    [DataListItem(Icon = "icon-active")]
    active,

    [Description("fa-regular fa-arrow-left")]
    [DataListItem(Icon = "icon-arrow-left")]
    arrowLeft,

// add as many or as little as you desire
}

IconVariant.cs

The description attribute is used to output the description to the editor, in this instance of using FontAwesome, "fak fa-active" is the key used to reference the icon inside of normal HTML (and on the Fontawesome website); you can make this whatever you like to be as descriptive to the editor as possible, in this solution the editors are familiar with the icon identifiers and having the key to the icon in Fontawesome contextually makes the most sense.

The DataListItem attribute is where the magic happens 🪄. Digging into the source code we can see that we can add a bunch of properties that will be rendered by Contentment.


namespace Umbraco.Community.Contentment.DataEditors
{
  [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
  public sealed class DataListItemAttribute : Attribute
  {
    public string Description { get; set; }

    public bool Disabled { get; set; }

    public string Group { get; set; }

    public string Icon { get; set; }

    public bool Ignore { get; set; }

    public string Name { get; set; }

    public string Value { get; set; }
  }
}

But - if we want to add our custom icons from font-awesome, or if you’re a dab hand with SVGs and have created your own, we need to upload them inside of the project in the backoffice in a specific file location; you can find more here on this YouTube video.

So that’s that, we’ve:

  1. Created a custom Enum
  2. Added our SVG icons into the App_Plugins/Icons/backoffice/icons directory

Now all we have to do is create our data-list property inside of the back office.

Creating a data-list inside of the backoffice is nice and straightforward — we create a new property type (making sure Contentment is installed inside of the solution).

Once we have this, we need to configure it to use a .NET Enumeration.

After we have selected our data source as our custom Enum, we can then begin to configure our list editor. There is a few options to consider but you just need to select one that contextually makes sense for your solution. 

In my example, I'm using the "Item Picker" list editor as it provides an Umbraco style overlay.

A screenshot of the available list views

List Editor picker

…and voila - we have our font-awesome icons (and custom icons) rendered in a friendly picker for the editor.

Our property, when using Models Builder is fully typed and available to us as an Enum too!


///<summary>
/// Icon
///</summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "10.6.0+d86e4b2")]
[ImplementPropertyType("icon")]
public virtual global::24Days.Shared.IconVariant Icon => this.Value<global::24Days.Shared.IconVariant>(_publishedValueFallback, "icon");

Which means we can just reference it super cleanly in our view templates:


<ul>
	@foreach (var icon in Model.Icons)
	{
		<li>@icon </li>
	}
</ul>

So that’s it, setting up a custom icon-picker inside of Umbraco is a doodle with Contentment, we need to:

  1. Create an enum
  2. Ensure our icons are in the solution
  3. Create a property type
  4. Use it

Some useful further reading:

https://github.com/leekelleher/umbraco-contentment/blob/develop/docs/data-sources/data-source--enum.md

https://github.com/leekelleher/umbraco-contentment/blob/master/src/Umbraco.Community.Contentment/DataEditors/DataList/DataListItemAttribute.cs

https://github.com/leekelleher/umbraco-contentment/blob/master/docs/editors/data-list.md


Sean Thorne
Sean Thorne