I have a form that allows the user to edit my model. They can save the data, as well as publish it. When the user hits save I want to go ahead and save the form even if its doesnt pass validation so that can come back and finish filling it out later. But if they blur out of a field and its required I still want it to turn red and show the error message. So basically I want normal client side validation without it preventing the form from posting.
Is there a way to do that?
simply override the form submit and that should disable the validation.
$(function () {
$("form").submit(function () {
if (!$(this).valid()) {
//form is not valid
return true;
}
});
});
You dont need the check there obviously and can just return true, thats just to show you how to check if its valid.
Related
My web page uses Jquery to overload a screen. In this overlay, the user can type some detail and click the submit button.
What I'd like to do is, when the user clicks on submit, the overlay doesn't disappear (as it would do with a page refresh), but a message appears, such as "all done"
The question I have though, is, what is the correct return type? I've gotten myself into a muddle I'm sure.
I tried to make the return type string, and return the string. Sadly, this redirected me to a page with the string value.
I then thought I would need to return a ContentResult() with return Content(myString). The result was the same as returning a string.
I then tried to return void, and simply in my controller use ViewBag.Status ="All done"; This now takes me an empty page.
How can I make the message show "All done" or "Complete" without losing the state? Am I trying to do the impossible without Ajax or similar?
Yes, you are trying to do the impossible. When a controller action gets hit on a synchronous request (e.g. a form submission) you are always going to get a full-page load. That's exactly what a synchronous request is. In effect, the "refresh" has already happened before your action code even runs; the return type of the action is irrelevant. For partial updates, you need an asynchronous request, which means AJAX.
The typical approach to this would be to load in your overlay and then, submit the form from the overlay via AJAX, return a partial view and target a container with jQuery. You'd typically create some kind of generic wrapper for your overlays that will do this for all form posts within any overlay.
Alternatively, you could look at returning JSON and using a JavaScript templating engine like Handlebars to populate the view.
Either way it's a good idea to look at wrapping all of this up in some "generic" JavaScript code that will do the same thing for form posts in all of your overlays; then you can stop worrying about the client-side code and focus on just returning the right thing from your controller actions.
If you want to do that WITHOUT ajax, you will need to return the whole underlaying page again, including the popup in a visible state.
What you (probably) SHOULD do is to use ajax and return a json result. Something like this jQuery solution:
$(document).on('click', '[type="submit"]', function(){
var $form = $(this).closest('form');
$.ajax({
url: $form.action,
type: 'post',
data: $form.serialize(),
success: function(response){
// write success message to user
}
});
});
Our credit card processor (Braintree Payments) requires that we not use the "name" attribute on credit card fields (card number, expiration date, and CCV) to obviously make sure they don't get POSTed to the server unencrypted. I found a custom Extension to generate a name-less text box (How to extend html.textboxfor to remove the name attribute?). This works great, since it allows us to generate a text box without the name attribute, but it still adds all the other validation attributes and such automatically. But I have run into a problem.
When I use #Html.NameLessTextBoxFor(model => model.CardNumber) in my view, it correctly generates the text box without a name attribute. We also use Data Annotations in the View Model to generate unobtrusive validation. The visible problem on the actual website is that when there is a validation error with one of these name-less fields, the ValidationMessage span doesn't display any error messages. The name-less field correctly turns red, but the error messages don't display.
I believe I have deduced why this isn't working, but I can't figure out how to fix it. I looked at the generated HTML for the ValidationMessage span, and I see this attribute:
data-valmsg-for="MyViewModel.CardNumber"
That would be correct if my name-less field had the name attribute set like normal. But since I can't set the name attribute, how do I get the ValidationMessage to still work?
Scrub the name attrributes on submit would be something like:
$("form").submit(function () {
$(this.find(":input").removeAttr("name");
});
It's possible that this may be too late in the chain of events though, so you may have to preventDefault and repost the form, something like this:
$("form").submit(function (e) {
if($(this.find(":input[name]").length > 0) {
e.preventDefault();
$(this.find(":input").removeAttr("name");
$(this).trigger("submit");
}
});
Or indeed do as I did and code a callBack into unobtrusive validation to check if validation has passed and at that point remove the name attributes. Here are my notes on adding that callBack:
//Added the following to the onErrors function:
if ($.isFunction(callBackOnError)) {
setTimeout(function () {
callBackOnError();
}, 100);
}
//Then in the exposing declarative section of the plugin
onError: function (callBack) {
callBackOnError = callBack;
}
Have a play with it and see what you find. Keen to know your eventual conclusion, so please do update. Hope this has somewhat helped you.
This is kind of a unique issue, and I'm still fairly new to MVC, so I'll do the best I can to explain it. I have a page with a third party grid, where each row is a "Company" object. My model for the view is a CompanyManager object, with the search parameters as fields and the list to populate the grid. Users are able to select a row for editing, which brings up a popup. A button outside the grid also opens the same popup for creating a new record.
The content of the popup is in a partial view, AddEdit, and the model for it is the "Company" object. Along with other fields, there is also another third party grid with "Contacts" as records. From the third party grid of "Contacts", I can serialize the records and pass them along on submit.
My problem lies with submitting on the modal popup, which should close when successful and stay open when the Company model (or any Contacts in the grid) fails validation. What's the best way of going about the submit? Currently, I have a button that calls a JavaScript function. In this function, I've tried jquery $.submit, but since the form posts to Index, that would close the popup regardless. I've also tried $.post to post to an Ajax call, but I have a JSON result being returned in the controller for this, which didn't work as I expected- it just outputs the JSON as HTML.
If you do your ajax call with JQUERY like this:
$.ajax({
type: 'POST',
dataType: 'json',
url: '/url/', //url your posting to
data: $('#form-addedit').serialize(), //serialize the data in your form
success: function (result) {
//hide modal
}
});
You should get the JSON Result in 'result'. Notice the dataType says 'json' if it was 'html' it would expect html to be returned. The result will be put into the variable result in the success function call and you can do what you want with the variable then, and determine if you need to close the modal or not.
Also, make sure in your controller, that you are indeed receiving an ajax call - Request.IsAjaxRequest()
You can do this by having a regular button to submit the form, like you would on any in-page form. Set the id of the button, let's say to 'Submit'.
Then validate the form with jQuery and the .click function. Something along the lines of
$("#Submit").click(function () {
var value = $("#your_field").val();
if (/*check for invalid condition*/) {
$("#Error_message").show();
return false;
return true;
});
This should check the value of each field you need to validate. If the validation fails, show the user and error message and return false. This prevents the click event (form submit) from executing. If the validation checks pass, return true to allow the click event which will submit the form and close the window.
Is there a way to hook into MVC3 unobtrusive remote validation on the client, before data is submitted to the remote method, and after a result is returned from the remote method?
I am trying to tell a remote validator to only perform validation if the submit button is clicked. The normal behavior is to validate several times, such as during keypress, blur etc. This is no good, as the validation method in question needs to call a non-idempotent operation. I need to make sure that method is only invoked if the user has clicked the submit button.
If I could hook into a before event, I could set a field in the form that flags the submit button as being clicked or not. However I would need to reset this flag after the remote method returns a validation result.
Any other suggestions? This is for validating a password using the ASP.NET Membership Provider's Membership.ValidateUser(string username, string password) method. This method will increment the FailedPasswordAttemtCount each time an invalid password is sent, so I don't want it to execute during blur, keypress, etc.
You could override the default validation options for the current page:
$.validator.setDefaults({
onkeyup: false,
onfocusout: false,
onsubmit: true
});
The solution above didn't resolve this for me. Somehow, the validator setting was not being set. So, I implemented the following and it worked:
$(function () {
var settings = $.data($('form')[0], 'validator').settings;
settings.onkeyup = false;
});
I have something like this:
I am using Ajax.BeginForm and its updatetargetid is a div which basically informs user whether it was successfully submitted or not and the problem, if any.
My controller function that is handling the form submission checks if there were any errors like duplicate entries and such and does re-checking of client-side rules and returns Content(....) accordingly.
This is what I'm using to clear form afterwards, but as you can see that the form would still get cleared even when my controller function has detected some problem that client-side didn't. I set AjaxOptions OnComplete = "onComplete".
function onComplete() {
if ($("#myForm").validate().form()) {
$("#myForm").clearForm();
}
}
Use function onComplete(ajaxContext){ } instead of function onComplete() {}
From the server end, if there are model validation errors, it usually means the validation summary (if supported) contains some error messages. Using ajaxContext, you can read the the response that is returned as part of ajax call and check the values of validation summary element.
Other option is to design a strategy between your controller and view - e.g. specify an error indicator as part of your response header and use this to decide whether to clear your form or not in OnComplete handler.
so then whats the problem? You simply dont call the onComplete function when there is a server side error. But instead display an error message to let the user know that nothing will happen as there was a server side error. And this way the form will not get cleared.
If everything does work on the server side, then only then will you call the onComplete function.
PK