-1

I have multiple checkboxes in my view and when testing different use cases, I noticed that if I do not select any textbox and hit the submit button it will redirect me to the next page. But in fact I want to add like a required attribute if possible for the user to select at least 1 checkbox. I tried adding the required attribute to the first checkbox but that would only mean that the user must select the first checkbox which is not what I want. Is this possible in .cshtml?

This is my view:

@using (Html.BeginForm("Data", "Controller"))
{
    for (int i = 0; i < Model.items.Count; i++)
    {
        int counter = 0;

        @Html.CheckBoxFor(r => Model.items[i].IsSelected)
        <label>  @Model.items[i].te</label><br />

        @Html.HiddenFor(h => @Model.items[i].Id)
        @Html.HiddenFor(h => @Model.items[i].Name)

        if (Model.items[i].Selected)
        {
            counter++;
        }
        else if (counter < 1)
        {
           RequiredCustom custom = new();

           custom.IsValid(Model.items);
        }



    }
        
    <input id="Button" type="submit" value="Next" />

}
10
  • In the post description your are talking about check-boxes. But the view above contains radio-buttons. Commented Aug 18, 2021 at 18:23
  • Sorry, I copied the incorrect view, please see the updated post @Jackdaw Commented Aug 18, 2021 at 19:15
  • No, it is not possible, you have to validate your model.plans contains at least 1 selected plain, (see custom data validations in c#) and then you could check if this property is valid and show custom error if not e.g. stackoverflow.com/questions/21263063/… Commented Aug 18, 2021 at 19:42
  • Here an example for custom attribute stackoverflow.com/a/33495692/2302522 try to implement similar that would fit your need. Commented Aug 18, 2021 at 19:49
  • @croban Thank you for sharing these with me. I was trying to implement either or but got stuck into this. Please see updated post where I show the controller that handles this Commented Aug 18, 2021 at 20:09

1 Answer 1

2

Well, If you don't want to use javascript then you have to use custom validator on asp.net backend side. Here is the complete steps how you could do this.

Custom Validator Method:

public class RequiredCustom : ValidationAttribute
        {
            protected override ValidationResult IsValid(object value, ValidationContext validationContext)
            {
                var viewModel = (ViewPhoneNumberInput)validationContext.ObjectInstance;

                var checkBoxCounter = 0;
                foreach (var plan in viewModel.plans)
                {
                    if(plan.IsSelected == true)
                    {
                        checkBoxCounter++;
                    }
                    if (plan.IsSelected == true && checkBoxCounter >0)
                    {
                        return new ValidationResult(ErrorMessage = "You have selected  "+ checkBoxCounter + " checkbox!");

                    }
                    else
                    {
                        return new ValidationResult(ErrorMessage == null ? "Please check one checkbox!" : ErrorMessage);
                    }
                    
                }

                return ValidationResult.Success;
            }
        }

Your Existing Model

public class ViewPhoneNumberInput
    {
        [Required(ErrorMessage = "You did not enter your phone number! Please enter your phone number!")]
        public String PhoneNumber { get; set; }
        [RequiredCustom(ErrorMessage = "Please select at least one checkbox")]
        public List<Plans> plans { get; set; }
    
    }

Views:

@model ViewPhoneNumberInput

@{ ViewBag.Title = " "; }

<h2>Select Your Plan</h2>

@using (Html.BeginForm("NewCustomerView", "StackOverFlow"))
{
    for (int i = 0; i < Model.plans.Count; i++)
    {
        int counter = 0;

        @Html.CheckBoxFor(r => Model.plans[i].IsSelected)
        <label>  @Model.plans[i].PlanName</label>


        @Html.HiddenFor(h => @Model.plans[i].PlanId)
        @Html.HiddenFor(h => @Model.plans[i].PlanName)

        <br />@Html.ValidationMessageFor(r => Model.plans)<br />
    }
    <p><strong>Phone Number</strong></p>
    @Html.TextBoxFor(r => Model.PhoneNumber)
    <p>  @Html.ValidationMessageFor(r => Model.PhoneNumber) </p>


    <input id="Button" type="submit" value="Next" />

}

Output:

enter image description here

Update:

I would preferably handle this following way:

 public class RequiredCustom : ValidationAttribute
        {
            protected override ValidationResult IsValid(object value, ValidationContext validationContext)
            {
                var viewModel = (ViewPhoneNumberInput)validationContext.ObjectInstance;

                var checkBoxCounter = 0;
                foreach (var plan in viewModel.plans)
                {
                    if(plan.IsSelected == true)
                    {
                        checkBoxCounter++;
                    }
                    if (plan.IsSelected == true && checkBoxCounter == 1)
                    {
                        return new ValidationResult(ErrorMessage = "You have selected checkbox!");

                    }
                    else
                    {
                        return new ValidationResult(ErrorMessage == null ? "Please check one checkbox!" : ErrorMessage);
                    }
                    
                }

                return ValidationResult.Success;
            }
        }

Note: This is the solution for the exception you were getting System.InvalidCastException: 'Unable to cast object of type 'PlanService.API.Models.ViewPhoneNumberInput' to type 'PlanService.API.Models.Plans. Because you were passing a list to the validator but previously it was expecting single list. Now its alright.

Now the validator model expecting a list of plans and can act accordingly.

Update Output

enter image description here

Hope it would help you to achieve your goal.

Sign up to request clarification or add additional context in comments.

12 Comments

He is asking for [... if possible for the user to select at least 1 checkbox...] your custom validator checks if every item inside List<> is selected
Ha ha, if you can set a condition for one item will that be a big deal for List<OfItems>? He needs to iterate of the iteam and finally check if at least one iteam selected. Just need to loop over, as he already knows.
:) i'm not sure if he knows that
If the OP requires, that also be provided. No worries
@croban Solution provided that you were concerned about.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.