haacked / aspnet-client-validation

A client validation library for ASP.NET MVC that does not require jQuery

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Why am i getting a client side validation for boolean field in a collection list ?

giannik opened this issue · comments

commented

Im getting the following client side error when clicking submit button :

image

viewmodel

    public class AddPartsViewModel
    {
        public AddPartsViewModel()
        {
            PartSelections = new List<PartSelectionViewModel>();
        }

        public EditTypeViewModel Type { get; set; }
        public List<PartSelectionViewModel> PartSelections { get; set; }
    }

    public class PartSelectionViewModel
    {
        public string PartName { get; set; }
        public string PartDisplayName { get; set; }
        public string PartDescription { get; set; }
        public bool IsSelected { get; set; }
    }

view


@model AddPartsViewModel
@{
    int i = 0;
}
<zone Name="Title"><h5>@T["Add Parts To \"{0}\"", Model.Type.DisplayName]</h5></zone>

@T["Choose the Parts to add to this Content Type."]

<form asp-action="AddPartsTo">
    @Html.ValidationSummary()
    <div class="mb-3">
        <ul class="list-group">
            @foreach (var partSelection in Model.PartSelections)
            {
                <li class="list-group-item">
                    <div class="form-check">
                        <input type="checkbox" class="form-check-input" asp-for="PartSelections[i].IsSelected">
                        <label class="form-check-label" asp-for="PartSelections[i].IsSelected">@partSelection.PartDisplayName</label>
                        <span class="form-text">@partSelection.PartDescription</span>
                    </div>
                    <input asp-for="PartSelections[i].IsSelected" type="hidden" />
                    <input asp-for="PartSelections[i].PartName" type="hidden" />
                </li>
                i++;
            }
        </ul>
    </div>
    <div class="mb-3">
        <button class="btn btn-primary save" type="submit">@T["Save"]</button>
        <a class="btn btn-secondary cancel" role="button" asp-route-action="Edit" asp-route-id="@Model.Type.Name">@T["Cancel"]</a>
    </div>
</form>


The validation failure is caused by this:

<input asp-for="PartSelections[i].IsSelected" type="hidden" />

You don't need to explicitly include that; asp-for automatically appends a hidden input to the form.

I've added a demo to reproduce: #72. Without the explicit hidden the markup looks like this:

<form method="post">
        <div class="form-field">
                <label>
                    <input type="checkbox" data-val="true" data-val-required="The IsSelected field is required." id="Numbers_0__IsSelected" name="Numbers[0].IsSelected" value="true" class="input-validation-valid">
                    One
                </label>
                <input type="hidden" data-val="true" data-val-required="The Name field is required." id="Numbers_0__Name" name="Numbers[0].Name" value="One" class="input-validation-valid">
                <!-- snip -->
            <span class="field-validation-valid" data-valmsg-for="Numbers" data-valmsg-replace="true"></span>
            <em class="results">Selected numbers: </em>
        </div>

        <input type="submit" value="Submit">
    <input name="__RequestVerificationToken" type="hidden" value="...">
    <input name="Numbers[0].IsSelected" type="hidden" value="false" class="input-validation-valid">
    <input name="Numbers[1].IsSelected" type="hidden" value="false" class="input-validation-valid">
    <input name="Numbers[2].IsSelected" type="hidden" value="false" class="input-validation-valid">
</form>

Including it adds an extra hidden that's confusing us:

                <input type="hidden" id="Numbers_0__IsSelected" name="Numbers[0].IsSelected" value="False" class="input-validation-valid">

Specifically we're confused by "False" instead of the auto-generated false:

// Checkboxes do not submit a value when unchecked. To work around this, platforms such as ASP.NET render a
// hidden input with the same name as the checkbox so that a value ("false") is still submitted even when
// the checkbox is not checked. We check this special case here.
if (elementType === "checkbox") {
const checkboxHiddenInput = element.form.querySelector(`input[name='${element.name}'][type='hidden']`);
if (checkboxHiddenInput instanceof HTMLInputElement && checkboxHiddenInput.value === "false") {
return true;
}
}

We could certainly patch that to also allow "False", but that's not necessary for the standard pattern to Just Work.

commented

I verify that it works. For some reason i had it there before moving from jquery validation