November Happy Hour will be moved to Thursday December 5th.

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.