mnsr
mnsr

Reputation: 12437

MVC3: Client Validation

I have a mini form that consists of all select boxes and checkbox lists.

I have the data annotations in the viewmodel already set up. So if i submit the form (without javascript enabled), ModelState.IsValid works like it's supposed to.

But in the client validation, I'm having issues. I have unobtrusive jquery validation on, but the when i do $("#form").valid(), it always returns true.

I'm not sure how to customize this and check for conditions. E.g., i have a checkboxlist which by default has nothing checked. So if nothing is checked, .valid() should return false. Also, 2 of the dropdowns have a 'please select' option as their first, but jquery still returns valid. Server side ModelState.IsValid works for both of these.

The following is an example:

@using (Html.BeginForm("index", "home", FormMethod.Post, new { @id = "miniForm" })) {
@Html.ValidationSummary(true)
@Html.AntiForgeryToken()

<div>
    @Html.LabelFor(m => m.NinjaType)
    @Html.DropDownListFor(m => m.NinjaType, Model.NinjaTypeList) // First value is '0'. Rest of the list is of type STRING
</div>

/// following is the rendered html code as i created a helper for it which i've omitted in this example
<ul>
    <li><input type="checkbox" id="poo1" name="pie" value="one" />one</li>
    <li><input type="checkbox" id="poo2" name="pie" value="two" />two</li>
    <li><input type="checkbox" id="poo3" name="pie" value="three" />three</li>
</ul>

<input type="submit" id="submitButton" />
}

If it helps, this is the POST Controller action:

public ActionResult Index(SuperDooperNinjaViewModel m)
{
    if (this.ModelState.IsValid)
        return Redirect("win");
    else 
        return Redirect("fail");
}

I was thinking that i'd do it the old fashioned way on $('#submitButton').click();, but I have a feeling there might be a better way to do this. Another way I've thought of, is turn it into an Ajax form. So in the server side response, instead of Redirect("fail");, i return a JsonResult.

So in summary, what would the best route be here to validating this form?

Thanks in advance

UPDATE:

ViewModel:

public class SuperDooperViewModel
{
    [Required]
    public string NinjaType {get;set;}
    public IEnumerable<SelectItemList> { get;set; }

    [Required]
    public string[] pie {get;set;} // checkbox
    public IEnumerable<string> PieList { get;set; } // list of values for checkbox
}

In jquery, i'm testing it like this:

$("#submitButton").click(function(e) {
    e.preventDefault();
    if ($("#miniForm").valid())
         alert("valid");
    else
         alert("fail");
});

Upvotes: 1

Views: 692

Answers (2)

mnsr
mnsr

Reputation: 12437

I'm not sure if this is the best way to do it, but for now, i've thrown the checkboxlist extension out, and just manually done this:

@foreach(var nt in Model.NinjaTypeList)
{
    <li>@Html.CheckBox("pie", new { @id = nt })</li>
}
@Html.HiddenFor(m => m.NinjaType)

In jquery, i've attached an event to the checkboxes:

$('input[name=pie]').click(function(){
    var pie = "";
    $('input[name=pie]').each(function(i) {
       if ($(this).is(':checked'))
           pie += $(this).val() + ';';
    });
    $("#NinjaType").val(pie);
});

In my controller:

public ActionResult Index(SuperDooperViewModel m, string[] pie)
{
    /// I've add the following as a work around:
    if (string.IsNullOrEmpty(m.NinjaType) // no reason it should be, but it's a sort of failsafe
    {
         if(pie.Any())
              m.NinjaType = string.Join(";", pie.Where(w => w != "false"));
    }

    // rest of the controller here
}

This basically does what I want, but it seems like a bit of a work around to me. Any improvements would be appreciated.

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1038790

For the dropdownlist it's simple:

public class SuperDooperNinjaViewModel
{
    [Required]
    public string NinjaType { get; set; }

    public SelectList NinjaTypeList { get; set; }
}

and in the view:

@Html.DropDownListFor(
    m => m.NinjaType, 
    Model.NinjaTypeList,
    "Please Select"
)

Now for the checkboxes you talked about some HTML helper that is generating them but I can't see this helper emitting any HTML5 data-* attributes which are used for unobttrusive validation.

Upvotes: 1

Related Questions