jquery datepicker and custom validation - jquery-ui

I need to add custom validation(I think) for validating input from an user. Here's my use case:
I'm using the jquery ui datepicker for selecting dates, with localization like this:
$.datepicker.setDefaults( $.datepicker.regional[ currentLocale ] );
I use the bassistance validation plugin, and using rules for date:true and such does not work with different formats(or if they do please tell me how!). So I've made my own date validation methods like this
$.validator.addMethod("validDate", function(value) {
return parseDateString(value) != null;
}, jQuery.validator.messages.date);
This all works very well except for the fact when selecting a date in the datepicker the validation is fired before the value of the componet is changed! So I actually validate the previous value....
Does anyone have a solution for me?
Thanks in advance:)

You could trigger validation upon the user closing the datepicker popup:
$("#birthdate").datepicker({
onClose: function() {
/* Validate a specific element: */
$("form").validate().element("#birthdate");
}
});
Using validate's element() function will enable you to validate a particular field immediately.
I've created an example here in which any date who's year != 2011 will trigger failed validation.

Related

Kendo validator not working on text change

I am using kendo controls for my project. I was using jquery validation to validate my controls at client side but as jquery validation is not working for kendo controls so I am using kendo validators to validate the controls.
I am using dataannotation validation with MVC 5 project. Here is sample dojo.
It is working perfect but the validation only appear on focus-out or blur event. Is there any way to validate control on change of value of control like jquery validation?
Update:
Here is the complete solution that helped me to resolve this issue:
if ($.validator !== undefined) {
$.validator.setDefaults({
ignore: [],
highlight: function (element, errorClass) {
element = $(element);
var highLightElement;
if (element.parent().hasClass("k-picker-wrap") ||
element.parent().hasClass("k-numeric-wrap")) {
highLightElement = element.parent().parent();
}
else if (element.parent().hasClass("k-widget")) {
highLightElement = element.parent();
} else if (element.parent().children('.k-upload-empty').length > 0) {
highLightElement = $(element.parent().children('.k-upload-empty')[0]);
} else {
highLightElement = element;
}
highLightElement.addClass('input-validation-error');
},
unhighlight: function (element, errorClass) {
element = $(element);
var highLightElement;
if (element.parent().hasClass("k-picker-wrap")
|| element.parent().hasClass("k-numeric-wrap")) {
highLightElement = element.parent().parent();
}
else if (element.parent().hasClass("k-widget")) {
highLightElement = element.parent();
} else {
highLightElement = element;
}
highLightElement.removeClass('input-validation-error');
}
});
}
You have 2 ways to meat your purpose:
Using jQuery Unobtrusive Validation with KendoUI
Background
As you know the Kendo UI Editor creates a different elements than HTML form elements. Other JavaScript editors work in a similar fashion. The actual HTML is hidden using CSS (display: none;), and therein lies the issue. By default jQuery Validation ignores hidden input fields. There are validation data-* attributes on the form elements, but since it is hidden, when the unobtrusive validation fires, the editor is ignored.
Solution
You have 2 ways to solve this issue and perfectly work with both technologies. Read the Making the Kendo UI Editor Work With jQuery Validations and if you have any problem for implementing, please read Kendo UI NumericTextBox With jQuery Validation as an example for NumericTextBox
Then, You may have problem to assign proper CSS class in case of validation. You can read adding jquery validation to kendo ui elements.
Just using KendoUI Validators
You should implement desired event for the validation purpose. Here you need onChange event to work like jQuery Unobtrusive Validation. Use the following code as it describes what to do:
$(document).ready(function () {
function widgetChange() {
//place validation logic
};
$("#dropdownlist").kendoDropDownList({
dataTextField: "text",
dataValueField: "value",
dataSource: data,
change: widgetChange
});
})
You may want to use both of them! So take a look at .Net Mvc 3 Trigger (other than submit button) Unobtrusive Validation
Update
A dojo for implementing with last solution which added a pattern="\d+" to search input with a validation message. The validation is called by filtering event for the same input. Note that you should use desired event based on UI element, here we used filtering for autocomplete instead of using change for DropDownList.
I recently found a new implementation which is looking good to try and test. That is available at aspnet-mvc getting-started validation

How can I disable the new Chrome HTML5 date input?

The recent update (V 20.x) of Chrome has broken one of my forms with the new built-in date and time input type. I'm calling jQuery UI datepicker on a date field and it used to work perfectly prior to the update. After the update, Chrome overrides my placeholder and renders the jQuery UI widget unusable.
Any ideas of how I can prevent Chrome from messing up with my input fields without changing their type?
You have a couple of different options.
You could detect that the user is using Chrome by sniffing the user agent string and preventing click events.
if (navigator.userAgent.indexOf('Chrome') != -1) {
$('input[type=date]').on('click', function(event) {
event.preventDefault();
});
}
User agent sniffing is a bad idea, but this will work.
The ideal approach in my mind is to detect whether the browser supports a native datepicker, if it does use it, if not use jQuery UI's.
if (!Modernizr.inputtypes['date']) {
$('input[type=date]').datepicker({
// Consistent format with the HTML5 picker
dateFormat: 'yy-mm-dd'
});
}​
Example - http://jsfiddle.net/tj_vantoll/8Wn34/
Of course since Chrome supports a native date picker the user would see that instead of jQuery UI's. But at least you wouldn't have a clash of functionality and the UI would be usable for the end user.
This intrigued me so I wrote up something about using jQuery UI's datepicker alongside the native control - http://tjvantoll.com/2012/06/30/creating-a-native-html5-datepicker-with-a-fallback-to-jquery-ui/.
Edit
If you're interested, I recently gave a talk on using jQuery UI's widgets alongside HTML5 form controls.
Slides
Video
To remove the arrow and spin buttons:
.unstyled::-webkit-inner-spin-button,
.unstyled::-webkit-calendar-picker-indicator {
display: none;
-webkit-appearance: none;
}
You can still active the calendar by pressing Alt+Down Arrow(checked on windows 10).
To disable, you need to add a little JavaScript:
dateInput.addEventListener('keydown', function(event) {
if (event.keyIdentifier == "Down") {
event.preventDefault()
}
}, false);
This works for me:
;
(function ($) {
$(document).ready(function (event) {
$(document).on('click input', 'input[type="date"], input[type="text"].date-picker', function (e) {
var $this = $(this);
$this.prop('type', 'text').datepicker({
showOtherMonths: true,
selectOtherMonths: true,
showButtonPanel: true,
changeMonth: true,
changeYear: true,
dateFormat: 'yy-mm-dd',
showWeek: true,
firstDay: 1
});
setTimeout(function() {
$this.datepicker('show');
}, 1);
});
});
})(jQuery, jQuery.ui);
I completely agree with TJ.
If you're doing any sort of editing, pre-filling, or dynamic setting of date values, you'll also need to know that as of 7/3/13 Chrome only honors the ISO standard date format (yyyy-mm-dd). It will display dates to the user in local format ('mm/dd/yy' for the US) but will ignore any values set in the HTML that are not ISO standard format.
To convert on page load, you can use TJ's user agent sniffer and do this:
if (navigator.userAgent.indexOf('Chrome/2') != -1) {
$('input[type=date]').each(function(){
var d = trim(this.getAttribute('value'));
if (d){
d = new Date(d);
var dStr = d.toISOString().split('T')[0];
this.value = dStr;
}
});
}
If, for example, you opt to disable the native datepicker and use jQuery's, you'll also need to set the date format to match Chrome's date field, or it won't display the input that the jQuery datepicker is sending it:
$('#myDate').datepicker({dateFormat: 'yy-mm-dd'});
Add those two things to the first option in TJ's answer and you have jQuery's datepicker working in Chrome without errors!
Relying on native datepickers is ideally the best solution. But when you need something that supports black-out dates, date ranges, or you just plain want it to look prettier, this will work.

How to programatically set a date in jquery mobile Datebox plugin 1.1.0

I want to programmatically set date for the input with datebox control, For this i know i can use something like this
$(element).trigger('datebox', {'method':'set', 'value':'dateString'});
but this doesn't seem to update the control(i.e when i open the calendar, it is set to current date and not equal to the value in the input field)
EDIT:
based on JTsage's pointers i overwrote the default dateformat to mm/dd/yyyy, using sth like this.
jQuery.extend(jQuery.mobile.datebox.prototype.options.lang, {
'en': {
dateFormat: '%m/%d/%Y'
}
});
jQuery.extend(jQuery.mobile.datebox.prototype.options, {
useLang: 'en'
});
Then i tried setting the date using sth like this
$(element).trigger('datebox', {'method':'set', value:'07/02/2012'});
but this date is not appearing when i navigate to the page..Interestingly when i tried updating the date from firebug console(being on that page) it updated the field as well as datebox control.
I have no idea why this is happening..Need help, please respond JT
So finally i fixed the issue, by doing this
jQuery.extend(jQuery.mobile.datebox.prototype.options, {
'overrideDateFormat': '%m-%d-%Y',
'overrideHeaderFormat': '%m-%d-%Y'
});
setting the value of the input field explicitly
$(element).val('06-21-2012');
and then refreshing the datebox
$(element).trigger('datebox', {'method':'set', 'value':'06-21-2012'});
I found th solution, try this
$(element).trigger('datebox', { 'method': 'doset' });

jQuery AutoComplete Trigger Change Event

How do you trigger jQuery UI's AutoComplete change event handler programmatically?
Hookup
$("#CompanyList").autocomplete({
source: context.companies,
change: handleCompanyChanged
});
Misc Attempts Thus Far
$("#CompanyList").change();
$("#CompanyList").trigger("change");
$("#CompanyList").triggerHandler("change");
Based on other answers it should work:
How to trigger jQuery change event in code
jQuery Autocomplete and on change Problem
JQuery Autocomplete help
The change event fires as expected when I manually interact with the AutoComplete input via browser; however I would like to programmatically trigger the change event in some cases.
What am I missing?
Here you go. It's a little messy but it works.
$(function () {
var companyList = $("#CompanyList").autocomplete({
change: function() {
alert('changed');
}
});
companyList.autocomplete('option','change').call(companyList);
});
this will work,too
$("#CompanyList").autocomplete({
source : yourSource,
change : yourChangeHandler
})
// deprecated
//$("#CompanyList").data("autocomplete")._trigger("change")
// use this now
$("#CompanyList").data("ui-autocomplete")._trigger("change")
It's better to use the select event instead. The change event is bound to keydown as Wil said. So if you want to listen to change on selection use select like that.
$("#yourcomponent").autocomplete({
select: function(event, ui) {
console.log(ui);
}
});
They are binding to keydown in the autocomplete source, so triggering the keydown will case it to update.
$("#CompanyList").trigger('keydown');
They aren't binding to the 'change' event because that only triggers at the DOM level when the form field loses focus. The autocomplete needs to respond faster than 'lost focus' so it has to bind to a key event.
Doing this:
companyList.autocomplete('option','change').call(companyList);
Will cause a bug if the user retypes the exact option that was there before.
Here is a relatively clean solution for others looking up this topic:
// run when eventlistener is triggered
$("#CompanyList").on( "autocompletechange", function(event,ui) {
// post value to console for validation
console.log($(this).val());
});
Per api.jqueryui.com/autocomplete/, this binds a function to the eventlistener. It is triggered both when the user selects a value from the autocomplete list and when they manually type in a value. The trigger fires when the field loses focus.
The simplest, most robust way is to use the internal ._trigger() to fire the autocomplete change event.
$("#CompanyList").autocomplete({
source : yourSource,
change : yourChangeHandler
})
$("#CompanyList").data("ui-autocomplete")._trigger("change");
Note, jQuery UI 1.9 changed from .data("autocomplete") to .data("ui-autocomplete"). You may also see some people using .data("uiAutocomplete") which indeed works in 1.9 and 1.10, but "ui-autocomplete" is the official preferred form. See http://jqueryui.com/upgrade-guide/1.9/#changed-naming-convention-for-data-keys for jQuery UI namespaecing on data keys.
You have to manually bind the event, rather than supply it as a property of the initialization object, to make it available to trigger.
$("#CompanyList").autocomplete({
source: context.companies
}).bind( 'autocompletechange', handleCompanyChanged );
then
$("#CompanyList").trigger("autocompletechange");
It's a bit of a workaround, but I'm in favor of workarounds that improve the semantic uniformity of the library!
The programmatically trigger to call the autocomplete.change event is via a namespaced trigger on the source select element.
$("#CompanyList").trigger("blur.autocomplete");
Within version 1.8 of jquery UI..
.bind( "blur.autocomplete", function( event ) {
if ( self.options.disabled ) {
return;
}
clearTimeout( self.searching );
// clicks on the menu (or a button to trigger a search) will cause a blur event
self.closing = setTimeout(function() {
self.close( event );
self._change( event );
}, 150 );
});
I was trying to do the same, but without keeping a variable of autocomplete. I walk throught this calling change handler programatically on the select event, you only need to worry about the actual value of input.
$("#CompanyList").autocomplete({
source: context.companies,
change: handleCompanyChanged,
select: function(event,ui){
$("#CompanyList").trigger('blur');
$("#CompanyList").val(ui.item.value);
handleCompanyChanged();
}
});
Well it works for me just binding a keypress event to the search input, like this:
... Instantiate your autofill here...
$("#CompanyList").bind("keypress", function(){
if (nowDoing==1) {
nowDoing = 0;
$('#form_459174').clearForm();
}
});
$('#search').autocomplete( { source: items } );
$('#search:focus').autocomplete('search', $('#search').val() );
This seems to be the only one that worked for me.
This post is pretty old, but for thoses who got here in 2016. None of the example here worked for me. Using keyup instead of autocompletechange did the job. Using jquery-ui 10.4
$("#CompanyList").on("keyup", function (event, ui) {
console.log($(this).val());
});
Hope this help!
Another solution than the previous ones:
//With trigger
$("#CompanyList").trigger("keydown");
//With the autocomplete API
$("#CompanyList").autocomplete("search");
jQuery UI Autocomplete API
https://jsfiddle.net/mwneepop/

ASP.NET Remote Validation only on blur?

I'm using the remote validation in MVC 3, but it seems to fire any time that I type something, if it's the second time that field's been active. The problem is that I have an autocomplete box, so they might click on a result to populate the field, which MVC views as "leaving" it.
Even apart from the autcomplete thing, I don't want it to attempt to validate when they're halfway through writing. Is there a way that I can say "only run validation n milliseconds after they are finished typing" or "only run validation on blur?"
MVC 3 relies on the jQuery Validation plugin for client side validation. You need to configure the plugin to not validate on key up.
You can switch it globally off using
$.validator.setDefaults({
onkeyup: false
})
See http://docs.jquery.com/Plugins/Validation/Validator/setDefaults and the onkeyup option here http://docs.jquery.com/Plugins/Validation/validate.
For future reference, I found it's possible to do this in combination with the typeWatch plugin (http://archive.plugins.jquery.com/project/TypeWatch).
Basically what you want to do is (in my case for a slug):
/*Disable keyup validation on focus and restore it to onkeyup validation mode on blur*/
$("form input[data-val-remote-url]").on({
focus: function () {
$(this).closest('form').validate().settings.onkeyup = false;
},
blur: function () {
$(this).closest('form').validate().settings.onkeyup = $.validator.defaults.onkeyup;
}
});
$(function () {
/*Setup the typeWatch for the element/s that's using remote validation*/
$("#Slug").typeWatch({ wait: 300, callback: validateSlug, captureLength: 5 });
});
function validateSlug() {
/*Manually force revalidation of the element (forces the remote validation to happen) */
var slug = $("#Slug");
slug.closest('form').validate().element(slug);
}
If you're using the vanilla typeWatch plugin, you'll have to setup a typeWatch for every element because the typeWatch callback doesn't give you access to the current element via $(this), it only passes the value.
Alternatively you can modify the typeWatch plugin to pass in the element (timer.el) and then you can apply a delay to all.
For some reason (maybe because of conflicts with the unobtrusive plugin), hwiechers' answer didn't work for me. Instead, I had to get the validator of my form with .data('validator') (as mentioned in this answer) and set onkeyup to false on it.
var validator = $('#form').data('validator');
validator.settings.onkeyup = false;
We had the same problem of focusing out the autocomplete textbox "DealingWithContactName" when autocomplete suggestion list pops up. Here we select the dynamically generated autocomplete list item on which the user clicks and set focus on to it. After 50ms we take the focus out from the textbox. It solved our problem.
$('body').on('click', 'ul.ui-autocomplete li a', function () {
$('#DealingWithContactName').focus();
window.setInterval(function () {
$('#DealingWithContactName').blur();
}, 50);
});
I wanted local validation to remain during onkeyup so that the user had a tighter feedback loop. This should only affect the remote validation (that results from RemoteAttribute):
$("[data-val-remote]").keyup(function () {
// Avoid hitting server validation during onkeyup. Wait for onfocusout.
return false;
});

Resources