PuneetGarg
+5
Jan 28, 2022
visibility 4350
star star star star star
(2 votes)

Custom radio control form element that displays the input box CMS 12

Episerver Forms does provide a lot of built-in functionality, but sometimes it is necessary to extend that functionality, which might give you some problems or difficulties. So in this post, I'm going to share my experience while customizing the Episerver form.

Note:- I'm doing this on CMS 12 and Episerver form 5.0.1

In this, we are going to extend the ability of the Selection element by inserting a text box with them.

1. Custom form element type

Since form elements are blocks, you create them the same way as any form of IContent. Instead of inheriting from BlockData inherit it from SelectionElementBlockBase<T>, ValidatableElementBlockBase, and many others, Right now we are going to work with the selection element so we are going to use SelectionElementBlockBase.

 public class InputBoxInChoiceElementBlock : SelectionElementBlockBase<ExtendedOptionItem>
    {
        [Display(GroupName = "Information", Order = -3000)]
        [EditorDescriptor(EditorDescriptorType = typeof(CollectionEditorDescriptor<ExtendedOptionItem>))]
        public override IEnumerable<ExtendedOptionItem> Items { get; set; }

        [Ignore]
        public override string PlaceHolder { get; set; }
        [Ignore]
        public override bool AllowMultiSelect { get; set; }

        public string GetDefaultSelectedString(ExtendedOptionItem item)
        {
            string defaultValue = this.GetDefaultValue();
            return this.GetDefaultSelectedString(item, defaultValue);
        }

        public string GetDefaultSelectedString(ExtendedOptionItem item, string defaultValue)
        {
            string str = item.Value;
            return (string.IsNullOrEmpty(str) || string.IsNullOrEmpty(defaultValue) || !((IEnumerable<string>)defaultValue.Split(',')).Contains<string>(str, (IEqualityComparer<string>)StringComparer.OrdinalIgnoreCase)) && (!item.Checked.HasValue || !item.Checked.Value || !string.IsNullOrEmpty(defaultValue)) ? string.Empty : "data-f-default-value=\"true\"";
        }
    }

2. Create a Class that inherits from IOptionItem.

This class will have all the properties of the radio button that you want to show i.e Label/Caption, Value, and others.

 public class ExtendedOptionItem : IOptionItem
    {
        [DisplayName("/episerver/forms/contentediting/optionitem/caption")]
        [Display(Order = 1000)]
        public virtual string Caption { get; set; }
        [DisplayName("/episerver/forms/contentediting/optionitem/value")]
        [Display(Order = 2000)]
        [RegularExpression("([^,])*", ErrorMessage = "/episerver/forms/contentediting/optionitem/containsinvalidcharacter")]
        public virtual string Value { get; set; }
        [DisplayName("/episerver/forms/contentediting/optionitem/checked")]
        [Display(Order = 3000)]
        public virtual bool? Checked { get; set; }
    }
    [PropertyDefinitionTypePlugIn]
    public class ExtendedOptionItemProperty : PropertyList<ExtendedOptionItem>
    {

    }

 3. Your view

You need to create your own rendering which somewhat looks like this. I didn't check for null in this code when you copy this does place your null checks.

@using (Html.BeginElement(Model, new { id = formElement.Guid, @class = "FormChoice" + cssClasses, data_f_type = "choice", aria_invalid = Util.GetAriaInvalidByValidationCssClasses(cssClasses) }, true))
{
    <fieldset aria-describedby="@Util.GetAriaDescribedByElementName(formElement.ElementName)">
       <legend class="Form__Element__Caption">@Model.Label</legend>        
            @foreach (var item in items)
            {
                var defaultCheckedString = Model.GetDefaultSelectedString(item);
                var checkedString = string.IsNullOrEmpty(defaultCheckedString) ? string.Empty : "checked";
                <label> <input type="radio" name="@formElement.ElementName" value="@item.Value" class="FormChoice__Input FormChoice__Input--Radio" @checkedString @defaultCheckedString data-f-datainput />@item.Caption</label>
            }        
        <label>
            <input type="radio" id="chk" name="@formElement.ElementName"  class="FormChoice__Input FormChoice__Input--Radio" data-f-datainput value=""/>  Other Amount ($) <input type="number" id="otherAmount" class="FormTextbox__Input wrap" data-f-datainput />
        </label>
    </fieldset>
    @Html.ValidationMessageFor(Model)
}

4. Java Script

Now we need to customize our text box like when you click on that particular radio button then only it shows and all. Do remember that by default Episerver form stores the value of the radio button, not the input box so we need to update it.

 $(document).ready(function () {
        // By Default Disable Input
        $("#otherAmount").attr('disabled', true);
        $(".wrap").css('opacity', '2');
        $("form input:radio").change(function () {
            if ($("#chk").is(":checked")) {
                $("#otherAmount").attr('disabled', false);
                $(".wrap").css('opacity', '2');
            }
            else {
                $("#otherAmount").attr('disabled', true);
                $("#otherAmount").val('');
                $(".wrap").css('opacity', '1');
            }
        });
        //Updating value of radio button
        $("#otherAmount").blur(function () {
            if ($("#chk").is(":checked")) {
                var otherAmountVal = parseInt($("#otherAmount").val());
                $("#chk").attr("value", otherAmountVal);
            }
        });
    });

That'll you need to customize the Episerver form.

Thank you

Puneet Garg

Jan 28, 2022

Comments

error Please login to comment.
Latest blogs
Composition Over Inheritance: Why Your Content Contract Is Not a Base Class

Inside the structural conformance pattern in SaaS CMS — from server-side inheritance to pipeline governance. A contract in Optimizely SaaS CMS is...

Vipin Banka | Sep 19, 2026

Optimizely Opti ID Integration: Why the API Key Was Missing from the DXP Management Portal

While working on an Optimizely CMS 12 Opti ID integration recently, we ran into an issue that initially appeared to be related to SSO authenticatio...

Madhu | Sep 18, 2026 |

Extending a Contract: What You Can Override

Contracts share fields across content types — but not every field setting can be overridden. Push the same contract onto several components, and CM...

Chirag Khanna | Sep 18, 2026 |

Building a Blazor Server UI Inside the Optimizely CMS 13 Admin Shell

What I learned shipping a Blazor Server UI inside Optimizely CMS 13 — Razor components in a NuGet package, the Blazor hub next to MapContent(),...

Stanisław Szołkowski | Sep 17, 2026 |