I am adding a whole bunch of Jquery validation rules dynamically. I am getting error because some of the textboxes are hidden based on user selection on the page before and therefore do not exist on the page. How do I check if the textbox exists before adding the validation rules?
Here are the validation rules being added:
$('[id$="txtLastName"]').rules('add', {
isSpecialChar: true,
maxlength: 13,
oneOrBothEntered: "txtFacility",
messages: {
oneOrBothEntered: "Either Provider Name or Facility Name must be entered"
}
});
$('[id$="txtFirstName"]').rules('add', {
isSpecialChar: true,
maxlength: 11,
conditionallyRequired: "txtLastName",
messages: {
conditionallyRequired: "This field is required."
}
});
...and a whole bunch more. So say txtLastName was hidden, this code breaks. How do I check first if txtlastname exists before adding the rules?
EDIT:
Per #sparky's comment, adding HTML for fields:
<div class="container1">
<span class="span150Padded">Last</span>
<asp:TextBox ID="txtLastName" runat="server" CssClass="textBoxMedium"></asp:TextBox>
</div>
<div class="container1">
<span class="span150Padded">First</span>
<asp:TextBox ID="txtFirstName" runat="server" CssClass="textBoxMedium"></asp:TextBox>
</div>
The reason I am adding the rules dynamically is because I am using master pages so my fields are renamed. I couldn't use the <%=textbox.ClientID%> method because my validation is in a separate js file which is referenced and called from my aspx page, and a js file won't recongnize something like that. After alot of back and forth, I have found that the cleanest solution was to add the validation rules dynamically.
If you have another suggestion for me, please let me know.
When using the jQuery Validate plugin or any of its methods, the plugin will not target all elements if your selector targets more than one element.
Use the jQuery .each() method to target all elements.
$('[id$="txtLastName"]').each(function() {
$(this).rules('add', {
...
});
});
EDIT:
If you want to avoid using .each(), then target the one element.
$('#justOneField').rules('add', {
...
});
Per the documentation
$("#myform").validate({
ignore: ":hidden"
});
Related
I'm hijaxing an existing form and POSTing to the server. jQuery validate does most of the validation but if validation fails on the server we return the errors to the client as JSON.
Below is the code that does that:
<script type="text/javascript">
$(function () {
$("form").submit(function (e) {
var $form = $(this);
var validator = $form.data("validator");
if (!validator || !$form.valid())
return;
e.preventDefault();
$.ajax({
url: "#Url.Action("index")",
type: "POST",
data: $form.serialize(),
statusCode: {
400: function(xhr, status, err) {
var errors = $.parseJSON(err);
validator.showErrors(errors);
}
},
success: function() {
// clear errors
// validator.resetForm();
// just reload the page for now
location.reload(true);
}
});
});
});
</script>
The problem is I can't seem to clear the validation errors if the POST is successful. I've tried calling validator.resetForm() but this makes no difference, the error messages added by the showError() call, are still displayed.
Note I'm also using the jQuery.validate.unobtrusive plugin.
You posted this a while ago, I don't know if you managed to solve it? I had the same problem with jQuery validate and the jQuery.validate.unobtrusive plugin.
After examining the source code and some debugging, I came to the conclusion that the problem comes from the way the unobtrusive plugin handles error messages. It removes the errorClass that the jQuery.validate plugin sets, and so when the form is reset, jQuery validate cannot find the error labels to remove.
I did not want to modify the code of the plugins, so I was able to overcome this in the following way:
// get the form inside we are working - change selector to your form as needed
var $form = $("form");
// get validator object
var $validator = $form.validate();
// get errors that were created using jQuery.validate.unobtrusive
var $errors = $form.find(".field-validation-error span");
// trick unobtrusive to think the elements were succesfully validated
// this removes the validation messages
$errors.each(function(){ $validator.settings.success($(this)); })
// clear errors from validation
$validator.resetForm();
note: I use the $ prefix for variables to denote variables that contain jQuery objects.
$("#form").find('.field-validation-error span').html('')
In .NET Core I have the form inside a builtin Bootstrap modal.
For now I'm manually removing the error message spans from their containers, once the modal is starting to show, by using the additional .text-danger class of the error message container like so:
$('#my-form').find('.text-danger').empty();
so that I don't rely on container .field-validation-error that might have been already toggled to .field-validation-valid.
The min.js versions of the libraries jquery.validate and jquery.validate.unobtrusive are loaded via the partial view _ValidateScriptsPartial.cshtml, so I played with them to see what resetForm() / valid() and native html form reset() do.
So in my case $('#my-form').data("validator").resetForm() only resets some validator internals, not the form and it doesn't trigger the onReset() function in the unobtrusive library. The $('#my-form').valid() indeed removes the errors in the modal, but only if the modal is fully shown and valid. The native html form reset() is the only one that triggers both onReset() of unobtrusive library, and then the resetForm() of the validator. So it seems like we need to trigger the native html form document.querySelector('#my-form').reset() to activate the reset functions of both libraries/plugins.
The interesting thing is that the unobtrusive library runs the simple jQuery empty() on the .field-validation-error class (the container of the error span message) only in its onSuccess() function, and not onReset(). This is probably why valid() is able to remove error messages. The unobtrusive onReset() looks like it's responsible only for toggling .field-validation-error class to .field-validation-valid. Hense we are left with a <span id="___-error">The error message</span> inside the container <span class="text-danger field-validation-error">...</span>.
May be I am wrong to clear the errors like this:
function clearError(form) {
$(form + ' .validation-summary-errors').each(function () {
$(this).html("<ul><li style='display:none'></li></ul>");
})
$(form + ' .validation-summary-errors').addClass('validation-summary-valid');
$(form + ' .validation-summary-errors').removeClass('validation-summary-errors');
$(form).removeData("validator");
$(form).removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse($(form));
};
I tried answer given in the comment by AaronLS but not got the solution so I just do it like this.
Maybe helpful to someone.
Here's the code I ended up using to clear/reset all errors. It's possible there's some redundancy in there, but it's working for me.
function removeValidationErrors(frmId) {
var myform = $('#' + frmId);
myform.get(0).reset();
var myValidator = myform.validate();
$(myform).removeData('validator');
$(myform).removeData('unobtrusiveValidation');
$.validator.unobtrusive.parse(myform);
myValidator.resetForm();
$('#' + frmId + ' input, select').removeClass('input-validation-error');
}
The reason this is still an issue (even 6 years on) is that jQuery Validation doesn't have an event handler for when your form is valid; only for when it's invalid.
Unobtrusive Validation taps into the Invalid handler to add your errors to your Validation Summary elements. (Specifically, any element with data-valmsg-summary=true.) But because there's no Valid handler, there's no way for Unobtrusive Validation to know when they can be cleared.
However, jQuery Validation does allow you to supply your own showErrors method, which is called after every validation check, whether the result is valid or invalid. Thus, you can write a custom function that will clear those validation summary boxes if your form is valid.
Here's a sample that will apply it globally. (You could apply it to specific instances of your validators by using settings, but since I always want this functionality, I just put it in the defaults object.)
$.validator.defaults.showErrors = function () {
if (!this.errorList.length) {
var container = $(this.currentForm).find("[data-valmsg-summary=true]");
container.find("ul").empty();
container.addClass("validation-summary-valid").removeClass("validation-summary-errors");
}
// Call jQuery Validation's default showErrors method.
this.defaultShowErrors();
};
This also has the benefit of clearing the validation summary box the moment your form is valid, instead of having to wait for the user to request a form submission.
I couldn't find this documented anywhere, but you should be able to reset the form by triggering a specific event, reset.unobtrusiveValidation, to which unobtrusive listens.
Example here:
.validation-summary-valid, .field-validation-valid { display: none; }
.field-validation-error { display: block; color: #dc3545 }
.input-validation-error { border: 1px solid #dc3545 }
.validation-summary-errors { background-color: #dc3545; color: #fff; margin-bottom: .5rem; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.5/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/4.0.0/jquery.validate.unobtrusive.js"></script>
<form id="testForm">
<div class="validation-summary-valid" data-valmsg-summary="true">
Validation Summary:
<ul><li style="display:none"></li></ul>
</div>
<div>
<label for="first_name">first name:</label>
<input data-val="true" data-val-required="the 'first name' field is required" name="first_name" id="first_name" />
<span class="field-validation-valid" data-valmsg-for="first_name" data-valmsg-replace="true"></span>
</div>
<div>
<label for="last_name">last name:</label>
<input data-val="true" data-val-required="the 'last name' field is required" name="last_name" id="last_name" />
<span class="field-validation-valid" data-valmsg-for="last_name" data-valmsg-replace="true"></span>
</div>
<button type="submit">Submit form (click first)</button>
<button type="button" onclick="$('#testForm').trigger('reset.unobtrusiveValidation')">Reset form (click second)</button>
</form>
What I want to achieve, is not the autocomplete effect. What I want to achieve is that when you type on google the search results come up almost inmediately without cliking on a search button.
I already did the ajax example with a search button, but I would like it to make it work while you type it shows the results in a table.
The problem is I have no idea where to start.
EDIT: To ask it in another way.
Lets suppose I have a grid with 1000 names. The grid is already present on the page.
I have a textbox, that when typing must filter that grid using AJAX, no search button needed.
Thanks
Use a PartialView and jQuery.ajax.
$(document).ready(function () {
$("#INPUTID").bind("keypress", function () {
if($(this).val().length > 2) {
$.ajax({
url: "URL TO CONTROLLER ACTION",
type: "POST|GET",
data: {query: $("#INPUTID").val(),
success: function (data, responseStatus, jQXHR)
{
$("#WRAPPERDIVID").html(data);
}
});
}
});
});
Then in your view:
<div>
<input type="text" id="INPUTID" />
</div>
<div id="WRAPPERDIVID"></div>
Edit
Also, you could build in some sort of timer solution that submits the request after say 1 second of no typing, so you don't get a request on every key press event.
Theres a good example you can check here try to type 's' in the search
if thats what you want
then the code and the tutorial is here
another good example here
If you are working on "filtering" a set already located on the page, then you seem to want to set the visibility of the items in the list, based upon the search criteria.
If so, then first, you need to first establish your HTML for each item. You can use the following for each item:
<div class="grid">
<div class="item"><input type="text" value="{name goes here}" readonly="readonly" /></div>
{ 999 other rows }
</div>
Then, you must use some jquery to set each row visible/invisible based on the search criteria:
$("#searchBox").live("change", function () {
$("div[class='grid'] input").each(function () {
var search = $("#searchBox").val();
if ($(this).val().toString().indexOf(search) != -1)
$(this).parent().show();
else
$(this).parent().hide();
});
});
This will cause the visibility of each item to change, depending on whether or not the text in the search box matches any text in the item.
jQuery.validate stops my form from being submitted. I would like it to just show the user what is wrong but allow them to submit anyway.
I am using the jquery.validate.unobtrusive library that comes with ASP MVC.
I use jquery.tmpl to dynamically create the form and then I use jquery.datalink to link the input fields to a json object on the page. So my document ready call looks something like this.
jQuery(function ($) {
// this allows be to rebind validation after the dynamic form has been created
$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse($("form"));
// submit the answers
$("form").submit(function(e) {
$("input[name=jsonResponse]").val(JSON.stringify(answerArray));
return true;
});
}
I note that there is an option
$("form").validate({ onsubmit: false });
but that seems to kill all validation.
So just to recap when my form is rendered I want to show all errors immediately but I don't want to prevent the submit from working.
So after some research (reading the source code) I found I needed to do 2 things
add the class cancel to my submit button
<input id="submitButton" type="submit" class="cancel" value="OK" />
This stops the validation running on submit.
To validate the form on load I just had to add this to my document ready function
$("form").valid();
Hope this helps someone else
I have a need to disable validation on certain fields when certain events occur, so based on the suggestion in this thread: jQuery disable rule validation on a single field
I tried this:
$("form").validate({
ignore: ".ignore"
})
But I am finding that it disables all validation on all fields, not just those with class="ignore".
Am I doing something wrong with this?
How about trying:
$('#CompaniesGridform').validate({
ignore: ":disabled"
});
I'm currently doing it something like this
<button id="Submit" type="submit">Submit</button>
<script type="text/javascript">
$("#Submit").on("click", function () {
var validator = $("form").data('validator');
validator.settings.ignore = ".ignore";
});
</script>
Switch out .ignore for any jQuery selector or chain them up like ".ignore, input[type=hidden]"
I'm creating a brand new MVC3 site.
Client side validation enabled on the web.config
<appSettings>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>
Scenario #1: Output HTML generated after a failed (client side) validation:
<span data-valmsg-replace="true" data-valmsg-for="UserName" class="field-validation-error">
<span htmlfor="UserName" generated="true" class="">Please enter an email address</span>
</span>
Note the nested span tag where the innermost tag has a class=""
Scenario #2: Custom Server-side validation. With the same web.config configuration, I added a validation on the server to check for a custom business rule. The validation fails, I add the error to the ModelState.
The HTML generated looks like this:
<span data-valmsg-replace="true" data-valmsg-for="UserName" class="field-validation-error">Please enter a valid email address</span>
Note that just one span tag was generated, NOT a nested tag.
This behavior is making it a pain to deal with my CSS as I can't just style the .field-validation-error class as there are 2 different end results on my generated HTML.
IN SUMMARY: Client side validation generates just 1 span tag, server side validation generates 2 span tags.
QUESTION: Is this the indented behavior of the framework or am I doing something wrong?
Is this the indented behavior of the framework or am I doing something wrong?
You are not doing anything wrong. It's just how the jquery.validate.unobtrusive.js script works. So you may call this a missing feature, discrepancy, PITA, whatever but that's how they did it out of the box.
This being said the jquery validate plugin is extensible and we can tweak it as we like:
$.validator.setDefaults({
// customize the way errors are shown
showErrors: function (errorMap, errorList) {
if (errorList.length < 1) {
// because we have customized the way errors are shown
// we need to clean them up if there aren't any
$('.field-validation-error', this.currentForm).hide().attr('class', 'field-validation-valid');
$('.input-validation-error', this.currentForm).removeClass('input-validation-error');
return;
}
$.each(errorList, function (index, error) {
// simply toggle the necessary classes to the corresponding span
// to make client validation generate the same markup as server
// side validation
var element = $(error.element);
element.attr('class', 'input-validation-error');
element.next('span').show().text(error.message).attr('class', 'field-validation-error');
})
}
});
If you want to always use nested spans for your validation messages after server validation failure (for styling reasons), you can do the following:
$(document).ready(function(){
$('.field-validation-error').each(function(){
$(this).html($('<span>').text($(this).text()));
});
});