Sana Assistant (online)
Table of Contents

EntityTemplateFieldEditorExtension reference

This article provides reference material about EntityTemplateFieldEditorExtension class. All entity template field editor extensions have to be inherited from the EntityTemplateFieldEditorExtension which, in turn, inherits from the core Sana Commerce Cloud Extension class.

There is also generic class EntityTemplateFieldEditorExtension<TSettings> inherited from EntityTemplateFieldEditorExtension which provides template field editor extensions with possibility to use extra settings required to manage field value by editor. It takes type inherited from EntityTemplateFieldEditorSettings as a generic type parameter.

EntityTemplateFieldEditorExtension inheritance

Properties

EntityTemplateFieldEditorExtension

FieldType

The field type for which the editor can be used.

public override EntityTemplateFieldType FieldType => EntityTemplateFieldType.DeliveryDate;

Name

The unique name of template field editor among other editors.

public override string Name => "MyDeliveryDateEditor";

Title

The field editor title which will be shown in admin.

public override string Title => "My delivery date editor";

Methods

EntityTemplateFieldEditorExtension

Note

All code examples may contain nonexistent methods or properties. They are used as declarations only and should be created if they fit the designed extension or deleted if they do not.

CreateDefaultSettings

Creates default field editor settings.

This method should be used to create editor settings with default values.

public override EntityTemplateFieldEditorSettings CreateDefaultSettings() =>
        new DeliveryDateTemplateFieldEditorSettings() { AvailabilityInDays = 1 };

CreateFieldValueValidationAttributes

Creates collection of field value validation attributes.

This method should be used to create collection of ValidationAttribute for field value validation, for example to check whether correct date value was received from client.

public override IEnumerable<ValidationAttribute> CreateFieldValueValidationAttributes(
        TemplateFieldEditorSettings settings,
        IEntityTemplateFieldValueValidationContext context)
{
    yield return new DateValidationAttribute(
        Api.GetSanaText("ValidationDateIsInvalid", "The value has invalid date."));
    yield return new DateAvailabilityValidationAttribute(
        settings,
        Api.GetSanaText("ValidationDateIsNotAvailable", "The selected date is not available for delivery."));
}

FormatValueForDisplayAsync

Formats managed by the field editor value for display.

This method is used by Sana to format read only field value previously managed by the extension editor. External API calls can be made to get extra information required for value formatting, it is better to use MemoryCache with short lifetime for results in this case to prevent extra API calls.

public override ValueTask<string> FormatValueForDisplayAsync(
        object value,
        TemplateFieldEditorSettings settings,
        EntityTemplateFieldDisplayValueFormatContext context)
{
    var date = (DateOnly)value;
    return ValueTask.FromResult(date.ToLongDateString());
}

InitSettings

Initializes the field editor settings with additional data required for managing field value.

public override void InitSettings(TemplateFieldEditorSettings settings, EntityTemplateField field)
{
    base.InitSettings(settings, field);

    InitDeliveryDateSettings((DeliveryDateTemplateFieldEditorSettings)settings);
}

static void InitDeliveryDateSettings(DeliveryDateTemplateFieldEditorSettings settings)
{
    settings.NotAvailableDates =
    [
        DateOnly.FromDateTime(DateTime.UtcNow.AddDays(3)),
        DateOnly.FromDateTime(DateTime.UtcNow.AddDays(5)),
        DateOnly.FromDateTime(DateTime.UtcNow.AddDays(7)),
        DateOnly.FromDateTime(DateTime.UtcNow.AddDays(11)),
    ];
}

Check full example with all required classes

public class DeliveryDateTemplateFieldEditorExtension : EntityTemplateFieldEditorExtension<DeliveryDateTemplateFieldEditorSettings>
{
    public override string Name => "MyDeliveryDateEditor";

    public override string Title => "My delivery date editor";

    public override EntityTemplateFieldType FieldType => EntityTemplateFieldType.DeliveryDate;

    public override EntityTemplateFieldEditorSettings CreateDefaultSettings() =>
        new DeliveryDateTemplateFieldEditorSettings() { AvailabilityInDays = 1 };

    protected override void InitSettings(DeliveryDateTemplateFieldEditorSettings settings, EntityTemplateField field)
    {
        base.InitSettings(settings, field);
        InitDeliveryDateSettings(settings);
    }

    protected override IEnumerable<ValidationAttribute> CreateFieldValueValidationAttributes(
        DeliveryDateTemplateFieldEditorSettings settings,
        IEntityTemplateFieldValueValidationContext context)
    {
        yield return new DateValidationAttribute(
            Api.GetSanaText("ValidationDateIsInvalid", "The value has invalid date."));
        yield return new DateAvailabilityValidationAttribute(
            settings,
            Api.GetSanaText("ValidationDateIsNotAvailable", "The selected date is not available for delivery."));
    }

    protected override ValueTask<string> FormatValueForDisplayAsync(
        object value,
        DeliveryDateTemplateFieldEditorSettings settings,
        EntityTemplateFieldDisplayValueFormatContext context)
    {
        var date = (DateOnly)value;
        var displayValue = settings.LongFormat ? date.ToLongDateString() : date.ToShortDateString();

        return ValueTask.FromResult(displayValue);
    }

    static void InitDeliveryDateSettings(DeliveryDateTemplateFieldEditorSettings settings)
    {
        settings.NotAvailableDates =
        [
            DateOnly.FromDateTime(DateTime.UtcNow.AddDays(3)),
            DateOnly.FromDateTime(DateTime.UtcNow.AddDays(5)),
            DateOnly.FromDateTime(DateTime.UtcNow.AddDays(7)),
            DateOnly.FromDateTime(DateTime.UtcNow.AddDays(11)),
        ];
    }

    sealed class DateValidationAttribute(string errorMessage) : ValidationAttribute(errorMessage)
    {
        public override bool IsValid(object? value)
        {
            if (value is null)
                return true;

            return value is DateOnly;
        }
    }

    sealed class DateAvailabilityValidationAttribute(
        DeliveryDateTemplateFieldEditorSettings settings,
        string errorMessage)
        : ValidationAttribute(errorMessage)
    {
        public override bool IsValid(object? value)
        {
            if (value is null)
                return true;

            if (value is DateOnly date)
                return ValidateDate(settings, date);

            return true;
        }

        static bool ValidateDate(DeliveryDateTemplateFieldEditorSettings settings, DateOnly date)
        {
            var firstAvailableDate = DateOnly.FromDateTime(DateTime.UtcNow.AddDays(settings.AvailabilityInDays));
            if (date < firstAvailableDate)
                return false;

            if (settings.NotAvailableDates is { Count: > 0 })
                return !settings.NotAvailableDates.Contains(date);

            return true;
        }
    }
}

public class DeliveryDateTemplateFieldEditorSettings : EntityTemplateFieldEditorSettings
{
    [Display(Name = "AvailabilityInDaysTitle", Order = 10, Description = "AvailabilityInDaysDescription")]
    public uint AvailabilityInDays { get; set; }

    [Display(Name = "DeliveryDateDisplayLongFormat", Order = 20, Description = "DeliveryDateDisplayLongFormatDescription")]
    public bool LongFormat { get; set; }

    [ScaffoldColumn(false)]
    public List<DateOnly>? NotAvailableDates { get; set; }
}

See also