Add a custom dropdown provider for administration components

When editors create pages with Page builder, they utilize components (page templates, sections, widgets), prepared by the developers. Each component has properties, that editors set in the Xperience administration using UI controls, for example, a dropdown selector.

Example of a dropdown page template property in Xperience by Kentico administration

As a developer, you can populate an Xperience dropdown selector with data in two ways:

  1. Pass a “hardcoded” string of options, as you can see in this example.

  2. Create a dropdown provider that maps options dynamically.

This guide covers the second approach. In our example, we use enumeration to define the dropdown options.

Setting up dropdown mapping is an important building block for the later guides in this Page builder series, which use dropdown components heavily.

Prerequisites

This guide assumes you have:

  • basic knowledge of C# and .NET framework concepts
  • familiarity with the basics of Page builder in Xperience by Kentico

If you’d like to follow along with the example discussed in this guide, the main branch of our Quickstart guide repository is a great starting point.

If you are working on your own project, make sure your instance of Xperience by Kentico is version 28.0.0 or higher.

For a finished example implementation, take a look at the DropdownEnumOptionsProvider.cs file in the finished branch of our Quickstart guides repository.

To see this provider in action, check out LandingPageTemplateProperties.cs file in the same repo.

Implement a generic mapper class

The Xperience Dropdown selector has a DataProviderType property that can take a class, mapping a custom enumeration to specific dropdown options.

While it is viable to implement a custom class per enumeration, a reusable generic class will save you time and lines of code.

  1. Create a generic DropdownEnumOptionProvider class that:

    • implements IDropDownOptionsProvider
    • accepts struct and Enum as the generic type
    If you are working in the Quickstart guide repository, we recommend placing the class inside ~/Features/Shared/OptionProviders folder in the TrainingGuides.Web project.
  2. Implement the following methods:

    1. GetOptionItems
      • tells Xperience how to map the enumeration members to dropdown items.
    2. Parse
      • casts a string value to the enumeration type. The value from the dropdown selector control comes back as string by definition, so the method will come in handy later in your code.
    To work with enumerations, this guide’s example uses EnumsNET NuGet package. The library allows you to access the enumeration attributes, like Description, which is handy, for example, to store UI labels for each dropdown option.

Below is a complete code of a generic DropdownEnumOptionProvider class, for your reference:

DropdownEnumOptionProvider.cs

using System.ComponentModel;
using EnumsNET;
using Kentico.Xperience.Admin.Base.FormAnnotations;

namespace TrainingGuides.Web.Features.Shared.OptionProviders;

public class DropdownEnumOptionProvider<T> : IDropDownOptionsProvider
    where T : struct, Enum
{
    public Task<IEnumerable<DropDownOptionItem>> GetOptionItems()
    {
        // map enum members to DropDownOptionItem
        var results = Enums.GetMembers<T>(EnumMemberSelection.All)
            .Select(enumItem =>
            {
                // dropdown item label:
                // if available, use Description attribute, otherwise use enum item name
                string text = enumItem.Attributes
                    .OfType<DescriptionAttribute>()
                    .FirstOrDefault()?.Description
                    ?? enumItem.Name;
                
                // dropdown item value 
                string value = enumItem.Value.ToString();

                return new DropDownOptionItem { Value = value, Text = text };
            });

        return Task.FromResult(results.AsEnumerable());
    }
 
    public virtual T Parse(string value, T defaultValue) =>
        Enums.TryParse<T>(value, true, out var parsed)
            ? parsed
            : defaultValue;
}

Use the new mapper class

Let’s demonstrate the enumeration mapping on an existing dropdown selector property of the Landing page template in the main branch of our Quickstart guide repository.

If you are working on your own project, feel free to define a property and enumeration values that fit your use case. You will still be able to follow most of the steps below.

Define your enumeration

  1. Examine the LandingPageTemplateProperties.cs file in TrainingGuides.Web/Features/LandingPages. The dropdown values are currently defined by a string constant:
    LandingPageTemplateProperties.cs - BEFORE MAPPING
    
    ...
    private const string OPTIONS =
        "H1;Heading 1" + "\n" +
        "H2;Heading 2" + "\n" +
        "H3;Heading 3" + "\n" +
        "H4;Heading 4" + "\n" +
        "P;Paragraph" + "\n";
    
    [DropDownComponent(
        Label = "Message tag type",
        Options = OPTIONS,
        ExplanationText = DESCRIPTION)]
    public string MessageType { get; set; } = "H4";
    ...
    
  2. Define the LandingPageHeadingTypeOption enumeration accordingly.
    
    public enum LandingPageHeadingTypeOption
    {
        [Description("Heading 1")]
        H1,
        [Description("Heading 2")]
        H2,
        [Description("Heading 3")]
        H3,
        [Description("Heading 4")]
        H4,
        [Description("Paragraph")]
        P
    }
    

Each enumeration item should match one option in the dropdown component.

The Description of each item is what editors will see as labels in the Xperience administration. If you don’t define a Description attribute, the item’s name becomes the label by default.

Map the enumeration to the dropdown component

  1. Assign the type of DropdownEnumOptionProvider<YOUR_ENUMERATION> to the DataProviderType property of the DropDownComponent.
  2. Remove the Options property, which is no longer needed.
See below the complete new version of LandingPageTemplateProperties.cs, with LandingPageHeadingTypeOption enumeration mapped to the MessageType dropdown property.
LandingPageTemplateProperties.cs - AFTER MAPPING

   using System.ComponentModel;
using Kentico.PageBuilder.Web.Mvc.PageTemplates;
using Kentico.Xperience.Admin.Base.FormAnnotations;
using TrainingGuides.Web.Features.Shared.OptionProviders;
using TrainingGuides.Web.Features.Shared.OptionProviders.Heading;

namespace TrainingGuides.Web.Features.LandingPages;

public class LandingPageTemplateProperties : IPageTemplateProperties
{
    private const string DESCRIPTION = "Select the type of Html tag that wraps the home page message";

    [DropDownComponent(
        Label = "Message tag type",
        ExplanationText = DESCRIPTION,
        DataProviderType = typeof(DropdownEnumOptionProvider<LandingPageHeadingTypeOption>)
    )]
    public string MessageType { get; set; } = nameof(LandingPageHeadingTypeOption.H2);
}

// enumeration defining the dropdown values and labels
public enum LandingPageHeadingTypeOption
{
    [Description("Heading 1")]
    H1,
    [Description("Heading 2")]
    H2,
    [Description("Heading 3")]
    H3,
    [Description("Heading 4")]
    H4,
    [Description("Paragraph")]
    P
}

If you followed along with the example above, run the TrainingGuides.Web project. When you edit the Home page template in the Xperience administration, the Message tag type property should let you change the style of the “Welcome to Training guides!” message - the same way as before the refactor.

What’s next

You can now utilize the DropdownEnumOptionProvider class across your project, for dropdown selector properties of page templates, page builder sections, or widgets alike. As later guides in this series demonstrate, you can work with enumerations that are shared or reuse other enumeration values.

If you have been following along using the the Quickstart guide repository, take a look at the Landing page view in the finished branch. You’ll notice it utilizes a tag helper rather than an in-template logic you can see in your code. Enumeration option providers and this scenario are both well-suited to this kind of extraction.

Note, that not all Xperience UI form components have the DataProviderType property and support the dynamic data source.

If you’d like to read more about how to approach working with Page builder in Xperience by Kentico projects, Meet business requirements with Page builder provides a great introductory explanation.

The next guide of this series will walk you through the process of creating versatile page templates.