ComfortablyNumb
ComfortablyNumb

Reputation: 1456

MVC Validate At Least One Checkbox Or a Textbox is Selected

I have a form where either at least one checkbox must be checked OR a textbox is filled in.

I have a ViewModel that populates the CheckboxList and takes the selected values plus the textbox (other) value when required to a SelectedWasteTypes property within the ViewModel. I think my problem is I can't validate against this property as there is no form element on the view that directly relates to it. I've very new to MVC and this one has stumped me.

From the ViewModel

public List<tblWasteTypeWeb> WasteTypeWebs { get; set; }
public string WasteTypeWebOther { get; set; }
public string SelectedWasteTypes { get; set; }

View (segment)

@using (Html.BeginForm("OrderComplete", "Home"))
{
    //Lots of other form elements

    @for (var i = 0; i < Model.WasteTypeWebs.Count; i++)
        {
            var wt = Model.WasteTypeWebs[i];
            @Html.LabelFor(x => x.WasteTypeWebs[i].WasteTypeWeb, wt.WasteTypeWeb)
            @Html.HiddenFor(x => x.WasteTypeWebs[i].WasteTypeWebId)
            @Html.HiddenFor(x => x.WasteTypeWebs[i].WasteTypeWeb)
            @Html.CheckBoxFor(x => x.WasteTypeWebs[i].WasteTypeWebCb)
        }
        <br />
        <span>
            @Html.Label("Other")
            @Html.TextBoxFor(x => x.WasteTypeWebOther, new { @class = "form-control input-sm" })
        </span>

    //More form elements

    <input type="submit" value="submit" />
}

Controller Logic (if you can call it that)

[HttpPost]
public ActionResult OrderComplete(OrderViewModel model)
{
    var sb = new StringBuilder();
    if (model.WasteTypeWebs.Count(x => x.WasteTypeWebCb) != 0)
    {
        foreach (var cb in model.WasteTypeWebs)
        {
            if (cb.WasteTypeWebCb)
            {
                sb.Append(cb.WasteTypeWeb + ", ");
            }
        }
        sb.Remove(sb.ToString().LastIndexOf(",", StringComparison.Ordinal), 1);
    }

    model.SelectedWasteTypes = sb.ToString();

    if (!string.IsNullOrEmpty(model.WasteTypeWebOther))
    {
        if (!string.IsNullOrEmpty(model.SelectedWasteTypes))
        {
            model.SelectedWasteTypes = model.SelectedWasteTypes.TrimEnd() + ", " + model.WasteTypeWebOther;
        }
        else
        {
            model.SelectedWasteTypes = model.WasteTypeWebOther;
        }
    }
    return View(model);
}

I very much feel I'm up a certain creek... I've thought about using JQuery, but ideally I'd like server side validation to be sure this info is captured (its a legal requirement). However, if this can only be achieved client side, I will live with it.

Any suggestions?

Upvotes: 1

Views: 4048

Answers (2)

vortex
vortex

Reputation: 1058

I would suggest you to implement IValidatableObject in your ViewModel. Inside Validate( ValidationContext validationContext) method you can check weather your conditions are met. For example:

if(string.IsNullOrWhiteSpace(WasteTypeWebOther))
    yield return new ValidationResult("Your validation error here.");

Upvotes: 0

viperguynaz
viperguynaz

Reputation: 12174

Take a look at the MVC Foolproof Validation Library. It has validation attributes for what you are trying to accomplish: [RequiredIfEmpty] and [RequiredIfNotEmpty]. You can also take a look at my previous SO answer about Conditional Validation.

Upvotes: 2

Related Questions