MVC 3 unobtrusive validation - conditionally disable/enable validation - asp.net-mvc-3

I have a form that has an option to enter dimensions for:
Width & Height
Width
Height
And I have two container divs that I hide/show depending on which of the three options is selected:
<div class="editor-field" id="width-container">
#Html.EditorFor(model => model.Width)
#Html.ValidationMessageFor(model => model.Width)
</div>
<div class="editor-field" id="height-container">
#Html.EditorFor(model => model.Height)
#Html.ValidationMessageFor(model => model.Height)
</div>
If height is selected, then width is not displayed on the form, how can I disable the unobtrusive validation on the Width input field in a fashion that will allow me to easily re-instate it if the user changes their mind i.e. removing data-* attributes is not an option. I'm happy to create an CustomAttribute class to handle this BUT I do not want to have to hack the standard jquery files to make this work as it makes updating to new versions a headache down the track. If all else fails I'll use my usual trick of adding a value of 0 to the fields when they are not visible and then removing it when they are shown.
EDIT:
Please be mindful that when Width is not visible it is not a "hidden" field per se it's just a input tag that's not visible to the user because the parent div has a style of display:none

You can set up the jQuery validator that's processing your unobtrusive validation to ignore hidden elements:
jQuery.validator.defaults.ignore = ":hidden";
// the line above is outside any $(document).ready(...) or similar
$(document).ready(function(){
...
});
...

So it seems that this is the answer to my question (I went hunting again on Google hard to search for things that didn't relate to "hidden" fields):
https://stackoverflow.com/a/7673985/491950
e.g.
$("#height-container input[type='text']").attr("disabled", "disabled");
Thanks for your answers.

Related

How do I pass data from javascript to a kendo window defined in asp mvc cshtml file?

I have a kendo window defined in a cshtml file and opened from the client side via javascript. The window is meant to display error messages from validation checks done in javascript. Is there a way to pass a string to the window from javascript?
Here's the window definition in the cshtml file:
#(Html.Kendo().Window()
.Name("ErrorWindow")
.Title("INVALID")
.Content(#<text>
<div class="metro" style="height:136px; padding-left:30px; padding-top:20px">
<div style="padding:0px 20px 3px 0">
<div>
<p id="ErrorInfo">
</p>
</div>
</div>
<p style="padding-top:20px; padding-left:0px; padding-bottom:20px">
#(Html.Kendo().Button()
.Name("closeErrWndButton")
.HtmlAttributes(new { type = "button", #class = "k-primary", #style = "min-width:90px" })
.Tag("span")
.Content("OK")
.Events(ev => ev.Click("CloseErrorWindow"))
)
</p>
</div>
</text>)
.Modal(true)
.Resizable()
.Width(560)
.Visible(false)
)
Here's how it's opened in javascript:
var wnd = $("#ErrorWindow").data("kendoWindow");
wnd.center().open();
I'm hoping to do this completely client side if possible, ie. no ajax call.
It sounds like you want to raise a 'kendo-themed' message dialog box for the user to peruse.
Consider using the Kendo UI Dialog component. The examples state
Description
The Kendo UI Dialog is a modal popup that brings information to the user. It also provides actions through the action buttons to prompt the user for input or to ask for a decision. The component can also contain more complex UI elements that require the focus of the user. The Dialog widget is a subset of the Kendo UI Window widget where the most prominent difference is the added functionality for actions.
The example shows using an existing div as the basis of the dialog. You can however use a more sophisticated approach that will dynamically create, attach and destroy the dialog basis, all within a single closure function.

How to properly disable an Html Helper Textbox or TextBoxFor?

I have a razor display that is being used for entry. In one case, I would like the user to be able to populate the text box, in the other case, I would like to prevent the user from populating it. I am using code like:
#Html.TextBoxFor(model => model.Goop, new { #class = "text-box", maxlength = 2, onfocus = "javascript:this.select();" })
if (Model.Review.ReviewType.Equals("M"))
{
<script type="text/javascript">
$(function () {
$("#Goop").prop("disabled", true);
});
</script>
}
I have tried to do this several ways, jQuery (above), CSS attribs, javascript, ASP.NET... but all have the same issue: When the form is submitted, if the Goop textbox is disabled, the value for Goop in the model is Null. Ideas?
Thanks in advance!
Maybe it's not as cool without jQuery, but when I do this in my apps I do something along the lines of
if (Model.Review.ReviewType.Equals("M"))
{
#Html.DisplayFor(model => model.Goop)
#Html.HiddenFor(model => model.Goop)
}
else
{
#Html.TextBoxFor(model => model.Goop)
}
If a form element is disabled, it does not post a value. That's how it's supposed to work.
To work around this, you will need to do one of several things. You can enable the fields just before posting by intercepting the submit method. You can use a hidden field to store the data in addition to the disabled control. Or you can just assume the values on the controller side.
by the way, it should be .prop("disabled", "disabled"), which renders as disabled="disabled", that's standards compliant.

Client side validation not working for hidden field in asp.net mvc 3

I have got a hidden field with a validation for it as below
#Html.HiddenFor(m => m.Rating)
#Html.ValidationMessageFor(m => m.Rating)
The Rating property has Range validator attribute applied with range being 1-5. This is put inside a form with a submit button.
I have then got following jquery that sets the value in hidden field on some user event (Basically user clicks on some stars to rate)
$(".star").click(function(){
$("#Rating").val(2);
});
Now if I submit the form without the user event that sets the hidden field, the validation works. The error messages is displayed properly and it works all client side.
Now, in this situation, if I click on stars, that invokes the above javascript a sets the hidden field, the validation error message would not go away. I can submit the form after the hidden variable has some valid value. But I'm expecting that the client side validation should work. (When the hidden variable has been set with some valid value, the validation error should go away)
Initially I thought, the jquery validation would be invoked on some special events so I tried raising click, change, keyup, blur and focusout events myself as below
$(".star").click(function(){
$("#Rating").val(2);
$("#Rating").change();
});
But this is still not working. The error messages once appeared, does not go away at all.
You can wrap your hidden field with a div put somewhere but still inside the <form>. Add css to kick it to outer space.
<div style="position:absolute; top:-9999px; left:-9999px">
<input id="Rating" type="hidden" name="rating" >
</div>
Then add the following label to where you want to show the error:
<label for="rating" class="error" style="display:none">I am an an error message, please modify me.</label>
Client-side validation ignores hidden fields. You can set the "ignore" option dynamically but just to get it to work I did the following directlyl in the .js file.
For now this should do the trick.
In my aspx...
<%: Html.HiddenFor(model => model.age, new { #class="formValidator" }) %>
In jquery.validate.js
ignore: ":hidden:not('.formValidator')",
This turned out to be a very interesting issue. the default "ignore" setting is ignores hidden fields. The field was hidden in a jQuery ui plug-in. I simply added a class called "includeCheckBox" to the rendered input I wanted to validate and put the following line of code in...
var validator = $('#formMyPita').validate();
validator.settings.ignore = ':hidden:not(".includeCheckBox")';
if ($('#formMyPita').valid()) {....
In the code which sets the hidden field's value, manually invoke validation for the form, like so:
$("form").validate().form();
I think it is because hidden inputs don't fire any of these events.
What you could do instead would be to use a <input type="text" style="display:none" /> instead of the hidden field;
#html.TextBoxFor(m => m.Rating, new {display = "display:none"})

Validation messages not clearing in MVC 3.0 with unobtrusive jquery

I'm attempting to implement a simple client side validation in a web app I'm working on, and the actual validation message is working. However, when I correct the incorrect input and the control loses focus, the validation message doesn't clear and the invalid class remains on the control. Here's the relevant view code
#model Project.CommentViewModel
#using (Html.BeginForm())
{
#Html.ValidationSummary(true);
<div class="Comment">
<div class="CommentInfo">
Post New Comment:
</div>
<div class="CommentText">
<div class="commentEdit ">
#Html.TextAreaFor(x => x.CommentText, new { #class = "NewCommentTextBox" })
#Html.ValidationMessageFor(x => x.CommentText)
</div>
#Html.HiddenFor(x => x.ProjectID)
</div>
</div>
}
And the view model attribute
[StringLength(50)]
public string CommentText { get; set; }
As I mentioned earlier, once the comment gets too long and the control loses focus, the error message comes up as expected. When the error is fixed however, the error message doesn't disappear and the control stays red. My _Layout page has the relevant script files included in the right order, and my config file has the appSetting variables set correctly. Any idea what's wrong or where I should be looking for the problem at? Thanks very much for any advice.
Resolved the problem. A Telerik grid that was present elsewhere on the page seems to have been conflicting with the validation somehow and broke it. Manually registering the jquery validation scripts with the grid resolved the issue.
#(Html.Telerik().ScriptRegistrar().DefaultGroup(group =>
group.Add("jquery.validate.js").Add("jquery.validate.unobtrusive.js")))
I think they may have resolved this particular issue with a newer version of the Telerik library.

Toggle validation in MVC 3 Razor

I'm using MVC 3 with razor as the view engine and the unobtrusive client validation enabled.
I'm trying to create a form where the user has a radio button group to select their preferred contact method - either phone or email. Depending on the option selected, I want to show the appropriate textbox, but then also enable/disable the required validator for the appropriate textbox.
My markup looks something like this at the moment (Just starting out with MVC so please point out any obvious mistakes):
<div id="prefferedContact">
<p>Preferred Contact Method *</p>
<input type="radio" id="contactMethodEmail" name="PreferredContactMethod" value="email" #if (Model.PreferredContactMethod != "phone"){<text>checked="checked"</text>} /> <label for="contactMethodEmail">by email</label>
<input type="radio" id="contactMethodPhone" name="PreferredContactMethod" value="phone" #if (Model.PreferredContactMethod == "phone"){<text>checked="checked"</text>} /> <label for="contactMethodPhone">by phone</label>
</div>
<div id="contactMethodDetails" class="formItem">
<div id="emailAddressBox">
#Html.LabelFor(x => x.Email, "Email address")
#Html.TextBoxFor(x => x.Email, new { #class = "textbox" })
</div>
<div id="phoneNumberBox">
#Html.LabelFor(x => x.PhoneNumber, "Phone number")
#Html.TextBoxFor(x => x.PhoneNumber, new { #class = "textbox" })
</div>
</div>
</div>
</div>
There's some jquery function that adds an onclick event to the radio buttons to toggle between the two boxes depending on the selected value.
The Model - for these specific fields - doesn't have any required validation on it at the moment but is binding fine. Also, validation is working on other fields as expected
I really just need to get an idea of:
(a) is it possible to toggle validation on and off
(b) does this impact the ModelState validation in anyway (or do I need to customise it)
I had also thought of having the one textbox for the contact data, but I wanted to have regular expression validation for the email and for the phone number separately. If I was to have a single textbox, could I switch the validation rules on the textbox depending on the selected option???
Hope that's clear enough with enough information.
Thanks
Joel
You can perform class-level validation if you need to enforce rules based on multiple properties:
http://weblogs.asp.net/scottgu/archive/2010/12/10/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3.aspx
Unfortunately, this seems to only work server-side, so you'd have to implement custom client-side validation.
Another option would be to have two different models, one for each scenario (with common properties in a base class), but this might be a little more complicated.

Resources