UI form component visibility conditions

Form component visibility conditions control the visibility of inputs within the configuration dialogs of admin UI, Page Builder, and Form Builder components.

Visibility conditions are assigned directly to configuration properties of supported components via C# attribute notation (each property represents a field in the corresponding configuration dialog).

A visibility condition consists of logic that evaluates whether a given field is displayed – implemented in the condition’s Evaluate method – and, optionally, a set of configuration properties.

Define visibility conditions

Unless specified otherwise, all classes and members mentioned in this section can be found in the 

  • Kentico.Xperience.Admin.Base.Forms
  • Kentico.Xperience.Admin.Base.FormAnnotations

namespaces. 

Visibility conditions are defined and evaluated on the application’s back end (the ASP.NET Core project). Their architecture is summarized by the following diagram:

Visibility condition architecture overview

The visibility of an input is determined using:

  • contextual information from the system (e.g., about the current user)
  • other inputs in the form
  • completely custom logic

With this in mind, visibility conditions can be classified into two categories:

  1. Conditions without field dependencies – determine the visibility of an input based solely on external or contextual information and custom logic.
  2. Conditions with field dependencies – use other fields in the form to determine the visibility of an input.

Visibility conditions without field dependencies

This type of visibility condition determines field visibility using information external to the form itself (e.g., information about the current user). 

Visibility conditions must inherit from the VisibilityCondition<TProperties> base class, where

  • TProperties – holds properties required for the functionality of the condition. The class must inherit from the VisibilityConditionProperties base class.

    Visibility condition properties class
    
    
      public class MyVisibilityConditionProperties : VisibilityConditionProperties
      {
          // Properties required for the functionality of the condition...
      }
    
      

and implement the Evaluate method. The method must return either true – indicating that the field is visible, or false – indicating that the field is hidden. The condition’s configuration properties can be accessed via VisibilityCondition<TProperties>.Properties.

Visibility condition main class


public class MyVisibilityCondition : VisibilityCondition<MyVisibilityConditionProperties>
{
    public override bool Evaluate(IFormFieldValueProvider formFieldValueProvider)
    {       
        // Visibility evaluation...

        // Properties can be accessed via 'Properties'
        Properties.ConfigurationProperty1...
    }
}

Dependency injection support

Visibility conditions support constructor dependency injection. You can use dependency injection to resolve instances of services on which the visibility condition depends.

To make the condition assignable to properties, create a corresponding attribute class – see Assign visibility conditions.  

Visibility conditions with field dependencies

This type of condition uses inputs from other fields in the form to determine a field’s visibility. 

To implement this type of visibility condition:

  1. Create a regular visibility condition
  2. Add support for field dependencies
  3. Access their values when evaluating visibility
  4. Make the condition assignable to properties

Add support for field dependencies

Conditions with dependencies need to locally store the names of the fields (other configuration properties within the component configuration dialog) on which they depend. The system uses this information to mark fields on which at least one visibility condition depends. A change in a marked field’s input triggers a re-evaluation of all related visibility conditions.

For this purpose, the VisibilityCondition<TProperties> base class contains the virtual DependsOnFields property, which holds the collection of field names as IEnumerable<string>. This property needs to be overriden in the class implementing the visibility condition and assigned a collection of field names on which the visibility evaluation depends. The field names must be provided via configuration properties when assigning the visibility condition.

Xperience API provides native support for conditions that depend on one other field via the following classes:

  • VisibilityConditionWithDependencyProperties – visibility condition properties class with one predefined property – PropertyName. The property holds the name of the field on which the visibility evaluation depends. 

    Example - AnotherPropertyValueVisibilityConditionProperties usage
    
    
      public class MyVisibilityConditionProperties : VisibilityConditionWithDependencyProperties {
          // Additional configuration properties for 'MyVisibilityCondition'
      }
    
      // The implementation of the 'VisibilityConditionWithDependencyProperties' class from the Xperience API
      public class VisibilityConditionWithDependencyProperties : VisibilityConditionProperties
      {
          public string PropertyName { get; set; }
      }
    
      
  • VisibilityConditionWithDependency<TProperties> – extends the VisibilityCondition<TProperties> class with support for conditions that depend on a single other field. Intended to be used together with VisibilityConditionWithDependencyProperties. Ensures DependsOnFields is populated with the name of the dependency provided via VisibilityConditionWithDependencyPropertie.PropertyName.

    Example - AnotherPropertyValueVisibilityCondition usage
    
    
      public class MyVisibilityCondition : VisibilityConditionWithDependency<MyVisibilityConditionProperties>
      {
      }
    
      // The implementation of the 'VisibilityConditionWithDependency<TProperties>' class from the Xperience API
      public abstract class VisibilityConditionWithDependency<TProperties> : VisibilityCondition<TProperties>
              where TProperties : VisibilityConditionWithDependencyProperties, new()
      {
           // Assigns the name of the property on which the condition depends to the collection
           public override IEnumerable<string> DependsOnFields => Enumerable.Repeat(Properties.PropertyName, 1);
      }
    
      

This approach can be extended to write conditions that depend on N other inputs.  

Access field values

Visibility conditions can only depend on fields that precede the currently evaluated field in the given form. For example, if a form comprises inputs A, B, C a visibility condition assigned to C can only depend on fields A and B. Note that the field order in the resulting form can be influenced by the Order property specified when assigning editing components.

To work with the values of fields on which the condition depends, the Evaluate method provides an instance of IFormFieldValueProvider. The provider enables access to the values of all preceding form field inputs. For example, if a form comprises inputs A, B, C and visibility is currently being evaluated on C, IFormFieldValueProvider can be used to access the values of A and B.

To get field values, use:

  • TryGet<TType>(string fieldName, out var fieldValue) – returns the value of the given field as TType

where fieldName is the name of the dependency from which to retrieve the value (provided via a configuration property – e.g., VisibilityConditionWithDependencyProperties.PropertyName).

Example - AnotherPropertyValueVisibilityCondition usage


public class MyVisibilityCondition : VisibilityConditionWithDependency<MyVisibilityConditionProperties>
{
    public override bool Evaluate(IFormFieldValueProvider formFieldValueProvider)
    {
        // Gets the value of the field as object
        formFieldValueProvider.TryGet<string>(Properties.PropertyName, out var fieldValue);

        // Use the value in visibility evaluation...
    }
}

public class MyVisibilityConditionProperties : VisibilityConditionWithDependencyProperties
{
    // Additional configuration properties for 'MyVisibilityCondition'
}

Assign visibility conditions

Visibility conditions are supported in dynamically created configuration dialogs of Page Builder and Form Builder components and other admin UI components:

  • Page Builder
    • widget configuration and personalization
    • section configuration
    • page template configuration
  • Form Builder
    • form component configuration
    • form section configuration
  • Admin UI
    • form component configuration
    • validation rule configuration
    • visibility condition configuration

Visibility conditions are assigned using attribute notation to the properties of model classes defining the configuration dialogs of supported components. For example:

Example - visibility condition usage in widget properties


using Kentico.PageBuilder.Web.Mvc;
using Kentico.Xperience.Admin.Base.FormAnnotations;

public class BannerWidgetProperties : IWidgetProperties
{
    ...

    [CheckboxInputComponent(Label = "Show link", Order = 1)]
    public bool ShowLink { get; set; }

    [TextInputComponent(Label = "Link URL", Order = 2, WatermarkText = "Enter a URL...")]
    // The 'VisibleIfTrue' condition only shows link-related properties in the dialog if 'ShowLink' is selected
    [VisibleIfTrue(nameof(ShowLink))]
    public string LinkUrl { get; set; }

    [TextInputComponent(Label = "Link title", Order = 3)]
    // The 'VisibleIfTrue' condition only shows link-related properties in the dialog if 'ShowLink' is selected
    [VisibleIfTrue(nameof(ShowLink))]
    // The 'VisibleIfNotEmpty' condition hides 'LinkTitle' from the properties dialog until 'LinkUrl' is provided
    [VisibleIfNotEmpty(nameof(LinkUrl))]
    public string LinkTitle { get; set; } = String.Empty;
}

Multiple visibility conditions

A single property can have multiple visibility conditions assigned. The property is visible if all added visibility conditions are fulfilled.

However, be mindful not to create contradictory rulesets that could make the field permanently hidden.

Each visibility condition must have a corresponding attribute. When the attribute is used to annotate a property of one of the supported components, the condition applies to that property’s input.

Visibility condition attribute classes must inherit from VisibilityConditionAttribute or derived classes:

  • VisibilityConditionAttribute – for rules that depend only on data that can be obtained contextually (e.g., a user’s assigned role).
  • VisibilityConditionWithDependencyAttribute – for rules that depend on a single other field in the configuration dialog (e.g., the example snippet above). The class extends the base VisibilityConditionAttribute class with a property that holds the name of the field on which the condition depends. This pattern can be adapted for conditions with dependencies on an arbitrary number of inputs.

Declare all mandatory and optional properties of the corresponding validation rule as properties of the attribute class. The properties:

  • must be named identically to the properties in the visibility condition class. The system uses the property names to instantiate the corresponding condition.
  • must be of the same type as the corresponding property in the visibility condition.

Properties that are required for the condition to function can be forced via the attribute’s constructor.

Example - sample validation rule attribute


public class ValueIsBetweenVisibilityConditionAttribute : VisibilityConditionWithDependencyAttribute 
{
    public int Maximum { get; set; }

    public int Minimum { get; set; }

    // Use the attribute constructor to force properties required for the correct
    // functionality of the visibility condition
    public ValueIsBetweenVisibilityConditionAttribute(string propertyName,
              int max, int min) : base(propertyName)
    {
        Maximum = max;
        Minimum = min;
    }
}

To indicate the relation between the attribute class and the corresponding validation rule, decorate the validation rule class with the VisibilityConditionAttribute attribute.

Example - bind visibility condition and corresponding attribute


[VisibilityConditionAttribute(typeof(ValueIsBetweenVisibilityConditionAttribute))]
public class ValueIsBetweenVisibilityCondition : VisibilityConditionWithDependency<TProperties>

For the example above, every property decorated with ValueIsBetweenVisibilityConditionAttribute is assigned the ValueIsBetweenVisibilityCondition condition. 

Default visibility conditions

The following table provides an overview of visibility conditions provided with a default Xperience installation. All visibility condition attributes are located in the Kentico.Xperience.Admin.Base.FormAnnotations namespace.

Visibility condition

Attribute

Description

Visible if B empty

VisibleIfEmptyAttribute

The decorated property A is visible if property B is empty (an empty string, an empty collection, or null). 

Visible if B not empty

VisibleIfNotEmptyAttribute

The decorated property A is visible if property B is not empty.

Visible if B equal to

VisibleIfEqualToAttribute

The decorated property A is visible if property B is equal to the specified string or object.

Visible if B not equal to

VisibleIfNotEqualToAttribute

The decorated property A is visible if property B is not equal to the specified string or object.

Visible if B true

VisibleIfTrueAttribute

The decorated property A is visible if property B is (boolean) true.

Visible if B false

VisibleIfFalseAttribute

The decorated property A is visible if property B is (boolean) false.

Example

The following example shows how to implement a visibility condition that checks if the value entered into another input in the form falls into the specified integer interval. Based on the result, the condition displays or hides its assigned field accordingly.

From the task definition, we know that we need to create a visibility condition that depends on one other input in the form. To achieve this, we can use VisibilityConditionWithDependency<TProperties> and VisibilityConditionWithDependencyProperties provided by the Xperience API. The classes ensure our visibility condition gets correctly configured, leaving us to focus on the implementation of the Evaluate method and requried configuration properties.

The condition’s properties class needs to store two values – the lower and upper boundary of the accepted interval. Should the input fall outside this interval, the field to which this condition is assigned is hidden.

Properties class


using Kentico.Xperience.Admin.Base.Forms;
using Kentico.Xperience.Admin.Base.FormAnnotations;

public class ValueIsBetweenVisibilityConditionProperties : VisibilityConditionWithDependencyProperties
{
    public int Maximum { get; set; }

    public int Minimum { get; set; }
}

Within the condition’s main class, we implement the Evaluate method, access the value of the field on which the condition depends (using the field name provided when configuring the condition) via IFormFieldValueProvider and use it to evaluate the condition.

Visibility condition class


using Kentico.Xperience.Admin.Base.Forms;
using Kentico.Xperience.Admin.Base.FormAnnotations;

public class ValueIsBetweenVisibilityCondition : VisibilityConditionWithDependency<ValueIsBetweenVisibilityConditionProperties>
{
    public override bool Evaluate(IFormFieldValueProvider formFieldValueProvider)
    {
        // Gets the value of the field on which the condition depends
        formFieldValueProvider.TryGet<int>(Properties.PropertyName, out var dependeeField);

        return (dependeeField >= Properties.Minimum) && (dependeeField <= Properties.Maximum);
    }
}

Now we need to create the corresponding attribute to enable usage in component model classes.

ValueIsBetween attribute class


using Kentico.Xperience.Admin.Base.Forms;
using Kentico.Xperience.Admin.Base.FormAnnotations;

public class ValueIsBetweenVisibilityConditionAttribute : VisibilityConditionWithDependencyAttribute
{
    public int Maximum { get; set; }

    public int Minimum { get; set; }

    // The 'VisibilityConditionWithDependencyAttribute' base class enforces the field dependency via the constructor
    public ValueIsBetweenVisibilityConditionAttribute(string propertyName,
             int max, int min) : base(propertyName)
    {
        Maximum = max;
        Minimum = min;
    }
}

With the attribute created, add VisibilityConditionAttribute with the attribute type as the parameter to the condition’s main class to tie the attribute and visibility condition together.

Visibility condition and attribute relationship


using Kentico.Xperience.Admin.Base.Forms;
using Kentico.Xperience.Admin.Base.FormAnnotations;

[VisibilityConditionAttribute(typeof(ValueIsBetweenVisibilityConditionAttribute))] 
public class ValueIsBetweenVisibilityCondition : VisibilityConditionWithDependency<ValueIsBetweenVisibilityConditionProperties>

The visibility condition is now ready to be used.