Reputation: 12437
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
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
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