Search code examples
asp.net-mvc-5checkboxfor

CheckBoxFor value does not change when the user ticks the box


I have a checkBoxFor to be used on a JQuery form and bound to my model, My issue is that when a user checks or unchecks the box the value used for some Client side validation is always true and the value used for server side validation is always false. Why is my check box not updating the value?

View:

 <form id="companyForm">
    <fieldset>
        <p>
            @Html.LabelFor(model => model.allCompany, new { @checked = "checked" })
            @Html.CheckBoxFor(model => model.allCompany)
        </p>
        <p>
            @Html.LabelFor(model => model.hierarchyValidation)
            @Html.DisplayFor(model => model.hierarchyValidation)
            @Html.HiddenFor(model => model.hierarchyValidation)
            @Html.ValidationMessageFor(model => model.hierarchyValidation)
        </p>
        <!-- Allow form submission with keyboard without duplicating the dialog button -->
        <input type="submit" tabindex="-1" style="position:absolute; top:-1000px">
    </fieldset>
</form>

View Model

public class AXAddRoleViewModel {

    public bool allCompany { get; set; }

    [Display(Name = "HierarchySelectList")]
    [IsEmptyAttribute("hierarchyValidation", "allCompany")]
    public string hierarchyValidation { get; set; }
}

Client side validation:

var isApplicationValid = $('#application').valid();
var isHierarchyValid = $('#hierarchyValidation').valid();

if (isHierarchyValid && isCompanyValid) {
    var roleName = $("#roleName").val();
    var hierarchy = $("#hierarchyValidation").val().toString();

    var data = {
        "reasons": message,
        "hierarchyValidation": hierarchy
    };

    $.ajax({
        url: url,
        type: "POST",
        data: data,
        success: function (data, textStatus, jqXHR) {
            alert("Success");
        },
            error: function (jqXHR, textStatus, errorThrown) {
                alert("Error");
            }
        });
    }
}

Custom Validator attribute:

public enum Comparison
{
    IsEmpty,
    ContainsValue
}

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class IsEmptyAttribute : ValidationAttribute, IClientValidatable
{
    private const string DefaultErrorMessage = "{0} Is required if a value from {1} is not selected.";

    public string ValueLabel { get; private set; }
    public string CompaniesValue { get; set; }

    public IsEmptyAttribute(string valueLabel, string companiesValue)
        : base(DefaultErrorMessage)
    {
        if (string.IsNullOrEmpty(valueLabel))
        {
            throw new ArgumentNullException("otherProperty");
        }
        ValueLabel = valueLabel;
        CompaniesValue = companiesValue;
    }

    public override string FormatErrorMessage(string name)
    {
        return string.Format(ErrorMessageString, ValueLabel, CompaniesValue);
    }

    protected override ValidationResult IsValid(object value,
                          ValidationContext validationContext)
    {
        var allCompaniesSelected = validationContext.ObjectInstance.GetType()
                                   .GetProperty(CompaniesValue);
        var allCompaniesSelectedValue = allCompaniesSelected
                              .GetValue(validationContext.ObjectInstance, null);

        if (Convert.ToBoolean(allCompaniesSelectedValue) == false)
        {
            if (value == null)
            {

                return new ValidationResult(
                    FormatErrorMessage(validationContext.DisplayName));
            }
        }
        return ValidationResult.Success;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var clientValidationRule = new ModelClientValidationRule()
        {
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
            ValidationType = "isempty"
        };

        clientValidationRule.ValidationParameters.Add("companiesvalue", CompaniesValue);

        return new[] { clientValidationRule };
    }
}

Custom Validator javascript:

(function ($) {
    $.validator.addMethod("isempty", function (value, element, params) {
        if (this.optional(element)) {
            var allCompanies = $('#addRoleCompany_allCompany')
            if (allCompanies.val() == false) {
                var otherProp = $('#addRoleCompany_' + params)
                return (otherProp.val() != value);
            }
        }
        return true;
    });
    $.validator.unobtrusive.adapters.addSingleVal("isempty", "otherproperty");

}(jQuery));

Can anybody tell me where should I look to find the issue and what the problem is?

Thank you for any help with this problem.


Solution

  • It turns out that I had overlooked the fact that I need to pass the value from Jquery after checking if the box is ticked or not.

    A simple mistake. Thank you everyone who helped solve this with me.