How do I handle server side validation error if I have a form running inside a jQuery UI dialog?
-
10-07-2019 - |
Question
I have the following code in my controller after the user posts the form but if the validation fails (_applicationValidator.Validate), I normally reload the "Edit" view but in this case I want to keep the dialog open and simply show these errors inside the dialog.
Controller Code:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Update(ApplicationUpdater applicationUpdater_)
{
if (_applicationValidator.Validate(applicationUpdater_, ModelState, ValueProvider))
{
_repo.UpdateApplication(applicationUpdater_);
ApplicationsViewModel vm = new ApplicationsViewModel();
vm.Applications = _repo.GetApplications();
return View("Index", vm);
}
else
{
ApplicationViewModel vm = GetApplicationVM();
return View("Edit", vm);
}
}
View Code (jQuery)
$(".showEditPopup").click(function() {
$.post("Applications/ShowEdit",
{ recnum: $(this).parents('tr:first').attr("recnum") },
function(htmlResult) {
$("#EditUserControlDiv").remove();
$("#container").append(htmlResult);
$("#container select[multiple]").asmSelect();
$("#EditUserControlDiv").dialog(
{
height: 675,
width: 650,
modal: true
}
);
}
);
});
Solution
As said
But in this case i want to keep the dialop open and simply show these errors inside the dialog
Ok.
After openning the dialog, you have to
- hide previous error message
...
open: function(event, ui) {
$(".error").css("display", "none");
}
After clicking dialog button, you have to
- disable JQuery UI
- Show "loading..." image
- Send form
...
$("#loading").css("display", "block");
panel.dialog("disable");
panel.dialog("option", "disabled", true);
After response is loaded (You can use JSON as response), you have to
- Check whether it has errors.
...
// var response plays the role of JSON response
var response = {
"errors":[
{
"property-name":"name",
"error":"Name is required"
},
{
"property-name":"age",
"error":""
}
]
};
var hasErrors = false;
for(var i = 0; i < response.errors.length; i++) {
if(response.errors[i].error != "") {
hasErrors = true;
$("#" + response.errors[i]["property-name"] + "-error")
.text(response.errors[i]["error"])
.css("display", "block");
}
}
if(!hasErrors) {
panel.dialog("close");
alert("success form!");
} else {
panel.dialog("enable");
panel.dialog("option", "disabled", false);
}
Here you can see in Action
Notice you have a default behavior. So you can put it inside a external function
OTHER TIPS
Most convenient:
- Disable all input elements
- Do an Ajax post to the
Update
function - Handle the server response in your UI. E.g. closing the jQuery UI form, or showing validation errors.
Change your Update
function to return some wrapper object like:
return new { Succeeded = false, ValidationMessages = new [] { "Incorrect username" } };
$.post(/* postdata */, function(resp) {
if(resp.Succeeded) //close jQuery UI dialog
else {
for(var i = 0; i < resp.ValidationMessages; i++) alert(resp.ValidationMessages[i]));
}
});
You can build your postdata, by quering all input/textarea etc. elements, and saving them into an array, something like (untested):
var data = [];
$('input').each(function() {
data.push([ $(this).id, $(this).val() ]);
});
You could use the jQuery form plugin to create an Ajax version of the editing form:
$(".showEditPopup").click(function() {
function popDialog(htmlResult) {
$("#EditUserControlDiv").remove();
$("#container").append(htmlResult);
$("#container form").ajaxForm(function(result) {
// There may be an easier way (like testing for a
// certain string in the result)
// to detect the need to "repop"
if ($(result).find('form').length) {
popDialog(result);
} else {
$("#EditUserControlDiv").dialog('close'); // or remove
}
});
$("#container select[multiple]").asmSelect();
$("#EditUserControlDiv").dialog(
{
height: 675,
width: 650,
modal: true
}
);
}
$.post("Applications/ShowEdit",
{ recnum: $(this).parents('tr:first').attr("recnum") },
function(result) { popDialog(result); }
);
});