Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more

How to Set Value on DataElementBlockBase, or how to make a checkbox required?

Vote:
 

Hello, I have read that you can make a checkbox by using a selection element with only one selection item, however, I also needed to add a link to the "label" so I decided to make my own:

[ContentType(DisplayName = "Checkbox", GroupName = GroupNames.FormElements, GUID = "...")]
    [AvailableValidatorTypes(Include = new Type[]
    {
        typeof(RequiredValidator)
    })]
    public class CheckboxElementBlock : InputElementBlockBase
    {
        [ScaffoldColumn(false)]
        public override string Label { get; set; }

        [ScaffoldColumn(false)]
        public override string PlaceHolder { get; set; }

        [Display(
            Name = "Description",
            Order = -6999)]
        public virtual XhtmlString Body { get; set; }
    }

Here is the view:

@using System.Web.Mvc
@using EPiServer.Shell.Web.Mvc.Html
@using EPiServer.Forms.Helpers.Internal
@using EPiServer.Forms.Implementation.Elements
@model CheckboxElementBlock

@{
    var formElement = Model.FormElement;
    var cssClasses = Model.GetValidationCssClasses();
    //I tried this just to test
    Model.FormElement.Value = Model.PredefinedValue;
}

@using (Html.BeginElement(Model, new { @class = "FormSelection" + cssClasses, data_f_type = "input" }))
{
    <input type="checkbox" name="@formElement.ElementName" id="@formElement.Guid" @(Model.AttributesString) data-f-datainput
           aria-describedby="@Util.GetAriaDescribedByElementName(formElement.ElementName)"
           aria-invalid="@Util.GetAriaInvalidByValidationCssClasses(cssClasses)" value="@Model.PredefinedValue"
           style="max-width: 25px; display: inline-block !important;">
    <label for="@formElement.Guid" class="Form__Element__Caption"
           style="display: inline-block !important; vertical-align: middle !important;"
           >@Html.PropertyFor(mod => mod.Body)</label>
    @Html.ValidationMessageFor(Model)
}

My problem is that, when I mark this field required (view the RequiredValidator), the validation never passes. It does not matter if the checkbox is checked or not, I still get the message that this field is required. I did some digging (or decompiling) and found this code from the RequiredValidator: 

public override bool? Validate(IElementValidatable targetElement)
        {
            object submittedValue = targetElement.GetSubmittedValue();
            if (submittedValue is string)
            {
                return !string.IsNullOrWhiteSpace((string)submittedValue);
            }

            if (submittedValue is IEnumerable && !((IEnumerable)submittedValue).GetEnumerator().MoveNext())
            {
                return false;
            }

            return submittedValue != null;
        }

So, I have an idea that the submitted value might be null? Has anyone run into this or know how to solve my issue?

#306049
Aug 01, 2023 22:26
Vote:
 

I solved this by extending `ChoiceElementBlock` instead of `InputElementBlockBase`. The functionality I am after (required validation) already exists in the `ChoiceElementBlock` so it was easier to just use that one. Here is my model class, cleaning up some elements so that the "checkbox" functionality is built in:

[ContentType(DisplayName = "Checkbox", GroupName = GroupNames.FormElements, GUID = "...")]
    public class CheckboxElementBlock : ChoiceElementBlock
    {
        [ScaffoldColumn(false)]
        public override string Label { get; set; }

        [ScaffoldColumn(false)]
        public override IEnumerable<OptionItem> Items { get; set; }

        [ScaffoldColumn(false)]
        public override bool AllowMultiSelect { get; set; }

        [ScaffoldColumn(false)]
        public override string PredefinedValue { get; set; }

        [ScaffoldColumn(false)]
        public override string Feed { get; set; }

        [Display(
            Name = "Label",
            Order = -6999)]
        public virtual XhtmlString Body { get; set; }

        public override void SetDefaultValues(ContentType contentType)
        {
            base.SetDefaultValues(contentType);

            Items = new List<OptionItem>() { new OptionItem { Value = "x", Caption = "x" } };
            AllowMultiSelect = true;
            Label = null;
        }
    }
#306105
Aug 02, 2023 16:49
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.