Validator plugin firing with links and on submit - jquery-plugins

I have a web form which is split up into several HTML pages.
I am using the validation plug-in to check fields on submit and this is working great.
The spec says that users should be able to navigate through the form, both linearly (just using the submit buttons to go from page to page) and also to skip to any particular page.
I have a unordered list with the links at the top of each page. I'm looking to fire the validation both on submit and when one of these links is clicked but don't know if this is possible.
For info, I'm currently firing the validation this way:
$("form#courseDetails").validate({
rules: {
studiedBefore: "required" //Have you studied with us before
},
messages: {
studiedBefore: "Please indicate whether you have studied with us before."
}
});
Each form has an ID and validation for all the forms is in one JS file.
Not that it really matters, but the navigation is in <ul id="tabNav">
Any help much appreciated.
Thanks,
Phil

Check the .valid() method it provides. If you call that in click handlers attached to your links, you should be ok.

Related

MVC3 Razor Ajax partial page validation

I have a wizard style page that I want to validate a page at a time. So before the user can move off the (partial) page I submit the inputs from the div for validation. Client side validation works OK but on some pages there are one or more fields I need to validate on the server. Yes I know about remote validation.
I can get the server side validation done without a problem. The issue I have is how do I display the errors on the correct fields? I can locate the fields in the div and find the span where the error message is suppose to go. But I just can't get the message to display.
I must be missing something when updating the field span. I would have thouht that there is a jQuery routine to add error information to a field. I need something similar to the controllers AddModuleError. So when I get return from my $.Post I can set error text on the appropriate fields.
Any suggestions?
A potential solution to your problem might be in this article "Client side validation after Ajax Partial View result in ASP.NET MVC 3"
Basically, once you get your html from the post you can invoke validation using jQuery.validator.unobtrusive.parse()
As per the example in the article;
$.post("YourAction", { data: <your form data> },
function(htmlContent){
$('#container').html(htmlContent);
jQuery.validator.unobtrusive.parse('#content')
}
Worth looking into
If you are using the included RemoteAttribute, or the version I linked to in my answer to your other remote validation question, then you should not have to worry about displaying the error, as both work with the ValidationMessage helpers to automatically display errors.
Have you added Html.ValidationMessage(...) or Html.ValidationMessageFor(...) for each field to be validated?

Manually bind JQuery validation after Ajax request

I'm requesting an ASP.net MVC view into a live box and the view contains form fields that have been marked up with attributes to be used by JQuery's unobtrusive validators plug-in.
The client script is not however working and my theory is that its because the validation framework is only being triggered on page load which has long since passed by the time the MVC view has been loaded into the live box.
Thus how can I let the validation framework know that it has new form fields to fix up?
Cheers, Ian.
var $form = $("form");
$form.unbind();
$form.data("validator", null);
$.validator.unobtrusive.parse(document);
// Re add validation with changes
$form.validate($form.data("unobtrusiveValidation").options);
You may take a look at the following blog post. And here's another one.
Another option, rather trick, which worked for me. Just add following line in the beginning of the partial view which is being returned by ajax call
this.ViewContext.FormContext = new FormContext();
Reference
For some reason I had to combine bjan and dfortun's answers...
So I put this in my view:
#{
this.ViewContext.FormContext = new FormContext();
}
And this execute this after the ajax call finishes:
var form = $("#EnrollmentForm");
form.unbind();
form.data("validator", null);
$.validator.unobtrusive.parse(document);
form.validate(form.data("unobtrusiveValidation").options);
I had a similar issue. I had a form that was using Ajax requests to re-display a part of the form with different form fields. I used unobtrusive validation by manually doing it on the client side using the
#Html.TextBoxFor
for my text boxes. For some reason the validation works when attempting to submit with invalid fields (i.e., the text boxes get outlined in red and the appropriate error messages display with the content I put in the
data_val_required
attribute, for example.
However, after I click a button that makes an Ajax request to modify the form with different fields and then submit again, only the red outline on the invalid fields display, but no error messages are rendered.
bjan's trick worked for me, but I still can't see what was causing the issue. All the HTML necessary to carry out the client-side validation was there I just can't figure out why the error message attribute values wouldn't display.
All I can think of is that the jQuery validation code doesn't make a second attempt to check the form fields after a submit was made.

ASP.NET MVC 3 Dynamic Controls and Unobtrusive Validation

Good afternoon everyone. I was wondering if there is anyway to have the MVC framework automatically wire up the data-val* attributes on the controls or do we need to manually create and apply the attributes to dynamic content?
I have a view that initially calls a partial view passing in the main viewmodel. This partial view is bound to a complex property on my main viewmodel. The partial view simply contains a set of cascading dropdown lists. On initial load of the page I have a call to #Html.Partial("PartialName", Model), the two dropdown lists’ validation works perfectly if I try to submit without selecting proper values. I also have another button on the page that if clicked loads another instance of the partial view on the page. If I now try to submit the form these controls, although they are bound to the same model and although I have set the correct .ValidationMessageFor helpers, no validation appears for them since the dropdownlists do not appear to be generated with the data-val* attributes. Is there any way that I can get them to appear correctly? I also noticed that the associated <span /> tag associated to the .ValidationMessageFor is not generated either. Has anyone run into this problem as well, if so how did you resolved?
UPDATE
Here is the javascript function that I call to load the partial on the button's onClick event:
function AddNewVehicle() {
$.ajax({
type: 'GET',
url: '/ReservationWizard/AddVehicleToReservation',
data: $('#reservation-wizard-form').serialize(),
dataType: 'HTML',
async: true,
success: function (data) {
if (data != null) {
$('#vehicle-selection-container').append(data);
}
}
});
}
The problem is that if you are not inside a form context, the HTML helpers such as TextBoxFor do not output any client validation data-* attributes. The first time when the page loads you invoke your Html.RenderPartial inside an Html.BeginForm() but later when you use AJAX to append form elements there is no longer this form context and there won't be any data-* client validation attributes generated. One possible solution would be to put the form inside the partial and then update the entire form during the AJAX call and in the success callback re-parse the client validation rules using $.validator.unobtrusive.parse('#vehicle-selection-container').
But if you want to keep only a single element inside the partial you are pretty much on your own :-) Here's a blog post which covers your scenario that you might take a look at.
So what can I say: unobtrusive client validation is great on paper and Scott Gu's blog posts but at some stage of the development of real world applications people start to realize its limitations. That's one of the reasons why I directly use the jquery.validate plugin and no MS jquery.unobtrusive. And, yes I know that I repeat my server validation logic in the javascript and yes I don't care because I have total control. Oh, and on the server I use FluentValidation.NET instead of data annotations for pretty much the same reasons as the client side part :-)
So maybe some day in MVC 4 Microsoft will finally make validation right (imperative vs declarative) but until this day comes, we just need to be searching for workarounds.

jQuery Showing an Ajax loader during transmission & Prevent Multiple Submits

I have an app that has several different types of form elements which all post data to the server with jQuery AJAX.
What I want to do is:
Show a loader during AJAX transmission
Prevent the user from submitting twice+ (clicking a lot)
This is easy to do on a one off basis for every type of form on the site (comments, file upload, etc). But I'm curious to learn if that is a more global way to handle this?
Something that's smart enough to say:
If a form is submitting to the server and waiting for a response, ignore all submits
Show a DISABLED class on the submitted / clicked item
Show a loading class on the class="spinner" which is closest to the submit item clicked
What do you think? Good idea? Done before?
Take a look at the jQuery Global Ajax Event Handlers.
In a nutshell, you can set events which occur on each and every AJAX request, hence the name Global Event Handlers. There are a few different events, I'll use ajaxStart() and ajaxComplete() in my code sample below.
The idea is that we show the loading, disable the form & button on the ajaxStart() event, then reenable the form and hide the loading element inside the ajaxComplete() event.
var $form = $("form");
$form.ajaxStart(function() {
// show loading
$("#loading", this).show();
// Add class of disabled to form element
$(this).addClass("disabled");
// Disable button
$("input[type=submit]", this).attr("disabled", true);
});
And the AJAX complete event
$form.ajaxComplete(function() {
// hide loading
$("#loading", this).hide();
// Remove disabled class
$(this).removeClass("disabled");
// Re-enable button
$("input[type=submit]", this).removeAttr("disabled");
});
You might need to attach to the ajaxError event as well in case an AJAX call fails since you might need to clean up some of the elements. Test it out and see what happens on a failed AJAX request.
P.S. If you're calling $.ajax or similar ($.getJSON), you can still set these events via $.ajaxStart and $.ajaxComplete since the AJAX isn't attached to any element. You'll need to rearrange the code a little though since you won't have access to $(this).
I believe you have to do 2 for sure and 3 to improve usability of your app. It is better to keep backend dumb but if you have a security issue you should handle that too.

Hot to implement grails server-side-triggered dialog, or how to break out of update region after AJAX call

In grails, I use the mechanism below in order to implement what I'd call a conditional server-side-triggered dialog: When a form is submitted, data must first be processed by a controller. Based on the outcome, there must either be a) a modal Yes/No confirmation in front of the "old" screen or b) a redirect to a new controller/view replacing the "old" screen (no confirmation required).
So here's my current approach:
In the originating view, I have a <g:formRemote name="requestForm" url="[controller:'test', action:'testRequest']", update:"dummyRegion"> and a
<span id="dummyRegion"> which is hidden by CSS
When submitting the form, the test controller checks if a confirmation is necessary and if so, renders a template with a yui-based dialog including Yes No buttons in front of the old screen (which works fine because the dialog "comes from" the dummyRegion, not overwriting the page). When Yes is pressed, the right other controller & action is called and the old screen is replaced, if No is pressed, the dialog is cancelled and the "old" screen is shown again without the dialog. Works well until here.
When submitting the form and test controller sees that NO confirmation is necessary, I would usually directly redirect to the right other controller & action. But the problem is that the corresponding view of that controller does not appear because it is rendered in the invisble dummyRegion as well. So I currently use a GSP template including a javascript redirect which I render instead. However a javascript redirect is often not allowed by the browser and I think it's not a clean solution.
So (finally ;-) my question is: How do I get a controller redirect to cause the corresponding view to "break out" of my AJAX dummyRegion, replacing the whole screen again?
Or: Do you have a better approach for what I have in mind? But please note that I cannot check on the client side whether the confirmation is necessary, there needs to be a server call! Also I'd like to avoid that the whole page has to be refreshed just for the confirmation dialog to pop up (which would also be possible without AJAX).
Thanks for any hints!
I know, it's not an "integrated" solution, but have you considered to do this "manually" with some JS library of your choice (my personal choice would be jQuery, but any other of the established libraries should do the trick)? This way you wouldn't depend on any update "region", but could do whatever you want (such as updating any DOM element) in the response handler of the AJAX request.
Just a thought. My personal experience is that the "built-in" AJAX/JS stuff in Grails often lacks some flexibility and I've always been better off just doing everything in plain jQuery.
This sounds like a good use-case for using web flows. If you want to show Form A, do some kind of check, and then either move onto NextScreen or show a Dialog that later redirects to NextScreen, then you could accomplish this with a flow:
def shoppingCartFlow = {
showFormA {
on("submit") {
if(needToShowDialog())return
}.to "showNextScreen"
on("return").to "showDialog"
}
showDialog {
on("submit").to "showNextScreen"
}
showNextScreen {
redirect(controller:"nextController", action:"nextAction")
}
}
Then you create a showDialog.gsp that pops up the dialog.
--EDIT--
But, you want an Ajax response to the first form submit, which WebFlow does not support. This tutorial, though, will teach you how to Ajaxify your web flow.

Resources