How to clear an invalid date field on blur? (AngularJS) - javascript

Say I have an <input> field with the type='date' attribute. When it is untouched, it displays date as mm/dd/yyyy. Is there any way, using AngularJS ng-blur directive to clear the field back to this state when a user enters input, say 03/21/2016, deletes one of the fields (ie 03/dd/2016), and then clicks outside of ('blurs') the field?

ng-blur,
In your html
<input type="date" ng-model="date" ng-blur="blured()" />
In your controller
$scope.blured = function()
{
// check the date
// if invalid
$scope.date = null;
}
see also:
https://docs.angularjs.org/api/ng/directive/ngBlur

In your HTML
<input type="date" ng-model="date" ng-blur="blured(date,$event)" />
In your JS
$scope.blured= function (inputdate, e) {
if (!e.ctrlKey && !e.metaKey && (e.keyCode == 32 || e.keyCode > 46))
doFormat(e.target);
if (e.target.value.length == 10) {
$scope.IsValidDate(1, e.target.value);
}
}
//id is used to check which date control
//method is used to validate entered date in MM/dd/yyyy format
$scope.IsValidDate = function (id, dateValue) {
var formats = ['MM/DD/YYYY']
if (!moment(dateValue, formats).isValid()) {
if (id == 1) {
$scope.date = null;
}
}
}
Hope this work for you, it worked for me.

Related

Showing prefix code for phone numbers - Jquery

I have implemented jQuery International Telephone Input but the issue now is, when i select the country, the prefix code doesn't show. How can i achieve this please ?
View
<div class="form-group">
<label for="eventRegInput2">Phone Number</label>
<input type="tel" id="phone" class="form-control square" placeholder="" value="{{ old('phone') }}"name="phone" required>
</div>
JS code responsible for displaying the prefix of the country selected.
JS
// get the input val, adding the dial code if separateDialCode is enabled
_getFullNumber: function() {
var val = $.trim(this.telInput.val()), dialCode = this.selectedCountryData.dialCode, prefix, numericVal = this._getNumeric(val), // normalized means ensure starts with a 1, so we can match against the full dial code
normalizedVal = numericVal.charAt(0) == "1" ? numericVal : "1" + numericVal;
if (this.options.separateDialCode) {
prefix = "+" + dialCode;
} else if (val.charAt(0) != "+" && val.charAt(0) != "1" && dialCode && dialCode.charAt(0) == "1" && dialCode.length == 4 && dialCode != normalizedVal.substr(0, 4)) {
// if the user has entered a national NANP number, then ensure it includes the full dial code / area code
prefix = dialCode.substr(1);
} else {
prefix = "";
}
return prefix + val;
},
How can I achieve this please?
Assuming that your function is working (that format properly input text with area code, all you have to do is when user leave textbox you can call your function to format number. This snippet need also to check if user has input something in textbox and if it is a valid code. Apart from that this is the way to ensure that your format function run everytime user leaves textbox and update its value with output from your function.
$('#phone').on('blur', function() {
var value = $(this).val();
if(value) {
$(this).val(_getFullNumber());
}
});

Datepicker validation not functioning on first try

I am currently working on a site using MEAN. In this site, I am using html5 datepicker but since it is not supported on some browsers, I used jquery datepicker as fallback and successfully managed to make it work.
Another thing I want is to display an error message if the user's selected date is valid. A date is valid if it is between 1900-01-01 and the current date.
Now, the problem is whenever I select a date for the first time, I am getting the error message even though I selected a valid date. And upon selecting a valid date for the second time, the error message disappears. On the third try, I selected an invalid date but the error doesn't show. On the fourth try, I selected a valid date but the error displays. To make it short, the validation applies to the previous input and not on the current input.
Below is the code on my controller:
var elem = document.createElement('input');
elem.setAttribute('type', 'date');
if ( elem.type === 'text' ) {
$('#contactBirthdate').datepicker({
dateFormat: "yy-mm-dd"
});
}
$scope.checkDate = function() {
console.log('Entered check date funtion');
var now = new Date();
var minDate = new Date('1900-01-01');
var inputDate;
if ( elem.type === 'text' ) {
$scope.appointment.birthday = new Date($( "#contactBirthdate" ).val());
console.log('input date not supported');
inputDate = new Date($scope.appointment.birthday);
} else {
inputDate = new Date($scope.appointment.birthday);
}
console.log('inputDate ' + inputDate);
if (inputDate < now && inputDate > minDate) {
$scope.isValidDate = true;
} else {
$scope.isValidDate = false;
}
console.log($scope.isValidDate);
};
And in my HTML
<div class="form-field">
<input name="contactBirthdate" type="date" min="1900-01-01" max="{{minAge | date: 'yyyy-MM-dd'}}" id="contactBirthdate" placeholder="Your Birthdate"
value="" class="full-width" ng-model="appointment.birthday" required="" step="1" ng-blur="checkDate()" onkeydown="return false">
<label ng-show="contactForm.contactBirthdate.$touched && !isValidDate" id="contactName-error" class="error" for="contactBirthdate">
Invalid Birthdate</label>
</div>
I really hope someone can help me with this one.

How to allow only digits to be entered into an input[type="number"] field?

I have an input field in which the user should only be able to enter digits [0-9].
document.getElementById("integer").addEventListener('input', restrictToInteger);
function restrictToInteger() {
this.value = this.value.replace(/[^\d]/g, '');
}
<input type="number" id="integer" />
jsFiddle Demo
The problem is this: When I enter a number (eg. 1234) and then press dot (.), + or - the content of the input field is automatically deleted by the browser (value is set to "" = empty string). But why? Changing the type from number to text seems to fix the problem. But then I lose the up/down arrow functionality of the input field. Any ideas?
HTML 4 has an event called onkeypress. With that attribute we can do this without using additional JS:
<input type="number" onkeypress="return (event.charCode == 8 || event.charCode == 0 || event.charCode == 13) ? null : event.charCode >= 48 && event.charCode <= 57">
Here digits from 0 to 9 are allowed using the event.charCode from 48 to 57.
I think the reason that the browser clean the input value it is because a string with two dots it is not a number.
Some corrections about your code:
You need to change your expression regular if you want to accept number with decimal part. Now, you are only express that you want to accept digits [0-9] and no more chars.
To accomplish want you want, you need to change /[^\d]/g to /[^\d.]/g.
document.getElementById("integer").addEventListener('input', restrictToInteger);
function restrictToInteger()
{
this.value = this.value.replace(/[^\d.]/g, '');
}
<input type="number" id="integer" />
HOWEVER: If you define your input as number type, the regular expression is not needed. So, you just need to define the input like this and should your to your case:
<input type="number" id="integer" />
[THE SOLUTION]
To fully meet your needs, I came with a solution that catch the keydown event of the input and check if there is any '.' on the input. If yes, I prevent the char to go to the input.
document.getElementById("integer").addEventListener('keydown', restrictToInteger);
var lastCodeWasDot = false;
function restrictToInteger(e)
{
var inputValue = document.getElementById("integer").value;
var isDot = false;
var isDot = (e.keyCode && e.keyCode == 110) || (e.charCode && e.charCode == 190);
console.log(e.keyCode);
if(isDot && (inputValue.indexOf(".") > -1 || inputValue == "" || lastCodeWasDot)) {
e.preventDefault();
}
lastCodeWasDot = isDot;
}
<input type="number" id="integer" />
Explaning the solution:
The line of code var isDot = (e.keyCode && e.keyCode == 110) || (e.charCode && e.keyCode == 190) || false; is needed because cross browser compatibility.
I don't now why but if you try to get the value from an input number type in the firefox, and if the value finishes with a dot, the value that you will get will be without the last dot of the input. To fix that, I needed to add the variable lastCodeWasDot to fix this issue.
NOTE: The number input can accept floating point numbers, including negative symbols and the e or E character (check out this post)
Based on the answers of Alexandru-Ionut Mihai and natchiketa I created the following solution:
document.getElementById("integer").addEventListener("input", allowOnlyDigits);
function allowOnlyDigits() {
if (this.validity.valid) {
this.setAttribute('current-value', this.value.replace(/[^\d]/g, ""));
}
this.value = this.getAttribute('current-value');
}
<input type="number" id="integer" />
On input the value is checked for validity. If it is valid, all non-digits are removed and the value is stored in a custom attribute of the element. If the value is not valid, the previous value is restored.
Notes:
The RegEx-replace is required only for Internet Explorer as it allows you to enter , or . at the end of a number.
Tested in IE, Edge, Chrome and Firefox
Chrome still allows you to enter a + before and one , after the number.
I found one issue: If you initialize the field with a value, the value is lost when you first hit an invalid char on the keyboard.
Another issue: You can't enter a negative number.
The only problem was your input type. Change it to text and it should work !
function validate(e) {
var charCode = e.keyCode? e.keyCode : e.charCode
if (!(charCode >= 48 && charCode <= 57)) {
if(!(charCode>=37 && charCode<=40))
if(charCode!=8 && charCode!=46)
return false;
}
}
<input type="number" id="integer" pattern="[0-9]"
onkeydown="return validate(event)"/>
You can achieve your requirement by copying the old value of input and using setAttribute and getAttribute methods in order to store the values.
function myFunction(input){
input.setAttribute('current-value',"");
input.oninput=function(){
let currentValue=input.getAttribute('current-value');
if(input.value!='' || (currentValue>=1 && currentValue<=9))
input.setAttribute('current-value',input.value);
input.value=input.getAttribute('current-value');
}
}
<input type="number" oninput="myFunction(this)"/>
<input type="number" oninput="myFunction(this)"/>
<input type="number" oninput="myFunction(this)"/>
<input type="number" oninput="myFunction(this)"/>
<input type="number" oninput="myFunction(this)"/>
When you call oninput, the <input> element first calls its internal methods to handle the value. This prevents your function from seeing any actual erroneous characters, namely e+-. - all used by JavaScript to format numbers.
You can see this by adding console.log calls before and after changing this.value.
console.log(this.value);
this.value=this.value.replace(/[^\d]/g, '');
console.log(this.value);
There is never any difference!
If you try, for example:
console.log(this.value);
this.value+=1; // or *=2 for numerical fun
console.log(this.value);
you can see a difference.
So your function is hastening the normal internal calls <input type='number'/> would normally make when handling illegal input.
Can't quite see why the field is left blank and not 1 though.
I would switch to a cancelable event like keydown.
That way you can prevent the character from being typed in the first place:
var cancelEvent = function (e) {
e.preventDefault();
return false;
},
restrictToInteger = function restrictToInteger(e) {
var acceptableInput = /[0-9]/g,
clipboardKeys = /[zxcv]/ig,
field = e.key || e.char,
isClipboardOperation = (clipboardKeys.test(field) && e.ctrlKey),
inputIsAcceptable = field ? (
acceptableInput.test(field)
|| field.length > 1
|| isClipboardOperation
) : true;
if (!inputIsAcceptable) {
cancelEvent(e);
}
},
ensureIntegerValueOnPaste = function ensureIntegerValueOnPaste(e) {
var data = e.clipboardData || e.dataTransfer,
text = data.getData('text'),
int = parseInt(this.value + text, 10);
if (isNaN(int)) {
cancelEvent(e);
} else {
window.setTimeout(function () {
e.target.value = int;
}, 0);
}
},
input = document.getElementById("integer");
input.addEventListener('keydown', restrictToInteger);
input.addEventListener('drop', ensureIntegerValueOnPaste);
input.addEventListener('paste', ensureIntegerValueOnPaste);
<input type="number" id="integer" />
Updated fiddle: https://jsfiddle.net/838pa8hv/2/
Disclaimers:
Only tested in Chrome.
The test for field.length > 1 is to catch non-numeric keys that are valid as the up/down arrows have a value of ArrowUp and ArrowDown respectively. This also allows for keys like Shift (or Home, Backspace, Delete, etc.) to be pressed as well.
Edit:
To handle pastes (and drops), you can do the same thing in those respective events. Updated fiddle and code snippet above.
Edit:
If the expected usability is to be able to paste/drop partial numbers into the field and to not allow negative integers, then you can just change how int is defined in the ensureIntegerValueOnPaste function. Updated fiddle and code snippet above.
You don't need regular expression, you can use parseFloat() function. Your input type remains unchanged, there are still "arrows" to increase/decrease number and also it makes sure that your input will not start with zero.
document.getElementById("integer").addEventListener('input', restrictToInteger);
function restrictToInteger() {
this.value = parseFloat(this.value);
}
<input type="number" id="integer" />
You have to check if the value is not a number and then stop user.
document.getElementById("integer").addEventListener('input', restrictToInteger);
function restrictToInteger(e)
{
if(isNaN(e.data)){
alert("only numbers allowed");
}
}
<input type="number" id="integer" />

ng-disabled in Angular not working

In My Angular UI I want to disable a submit button if
1) All the inputs are null or empty
2) If the endDate field is less than the startDate itself
What I did is ...
<input type="submit" class="btn btn-default pull-right" style="width:100px;" value="Submit"
ng-disabled="groupMembershipUserInputForm.$invalid || !(!!groupmembership.chapterCode || !!groupmembership.groupCode ||
!!groupmembership.groupName || !!groupmembership.createdBy ||
!!groupmembership.createdDate || !!groupmembership.startDate ||
!!groupmembership.endDate || !!groupmembership.losCode
|| groupmembership.compareAgainstStartDate(groupmembership.endDate) )" />
All the strings empty/null checks are working fine except the date compare check .
In my controller the method looks like
$scope.groupmembership.compareAgainstStartDate = function (item) {
var startDate = $filter('date')(new Date($scope.groupmembership.startDate), 'MM/dd/yyyy');
var endDate = $filter('date')(new Date($scope.groupmembership.endDate), 'MM/dd/yyyy');
if (endDate < startDate) {
$scope.groupmembership.toggleInvalidInput = true;
}
else
$scope.groupmembership.toggleInvalidInput = false;
return $scope.groupmembership.toggleInvalidInput;
};
It is being hit , but I don't know why the disabling not happening if the date compare fails .
Please help me .
So first :
All the inputs are null or empty
For this just add a required to all your input/select/...
If you do so groupMembershipUserInputForm.$invalid will be true if one of the required fields is not filled.
This will simplify greatly you ng-disabled to the following :
ng-disabled="groupMembershipUserInputForm.$invalid ||
groupmembership.compareAgainstStartDate(groupmembership.endDate)"
This is a first valid working step. Now if you want to go further you could create a directive and have something like :
<input ng-model="afterDate" date-greater-than="beforeDate"/>
This will be usefull if you have other forms than need this. If you're interested to do this i suggest you to google something like "angular js custom validation form directive" and if you have trouble with that directive, after trying on your own, come back to us into another question.
FInally if you master custom validation form you could use angular-message. it's a little addon specifically designed to display error from forms.
Here is a sample code from https://scotch.io/tutorials/angularjs-form-validation-with-ngmessages :
<form name="myForm">
<input
type="text"
name="username"
ng-model="user.username"
ng-minlength="3"
ng-maxlength="8"
required>
<div ng-messages="userForm.name.$error">
<p ng-message="minlength">Your name is too short.</p>
<p ng-message="maxlength">Your name is too long.</p>
<p ng-message="required">Your name is required.</p>
<p ng-message="myCustomErrorField">Your name is <your custom reason></p>
</div>
<input type="submit" ng-disabled="myForm.$invalid"/>
</form>
Your logic pretty much right, I have doubt on your $scope.groupmembership.startDate and $scope.groupmembership.endDate because if I provide correct dates, then it is working as expected. Can you please try by providing some constant date to verify whether your function is behaving properly or not. For me it is working fine with actual date values.
$scope.startDate = $filter('date')(new Date("07/02/2016"), 'MM/dd/yyyy');
$scope.endDate = $filter('date')(new Date("0710/2016"), 'MM/dd/yyyy');
In your example dates are string type so you may not get correct result. To compare date first convert it to time using getTime() that will give you exact result. No need to use filter for date check.
just use like:
$scope.groupmembership.compareAgainstStartDate = function () {
var startDate = new Date($scope.groupmembership.startDate);
var endDate = new Date($scope.groupmembership.endDate);
if (endDate.getTime() < startDate.getTime()) {
$scope.groupmembership.toggleInvalidInput = true;
}
else
$scope.groupmembership.toggleInvalidInput = false;
return $scope.groupmembership.toggleInvalidInput;
};
Just convert startdate and enddate to milliseconds, and compare them.
Try the below code once:
$scope.groupmembership.compareAgainstStartDate = function () {
var startDate = new Date($scope.groupmembership.startDate).getTime();
var endDate = new Date($scope.groupmembership.endDate).getTime();
if (endDate < startDate) {
$scope.groupmembership.toggleInvalidInput = true;
} else {
$scope.groupmembership.toggleInvalidInput = false;
}
return $scope.groupmembership.toggleInvalidInput;
};

Want to prevent a textbox from becoming empty with javascript

So i already have a textbox in which you can only enter numbers and they have to be within a certain range.The textbox defaults to 1,and i want to stop the user from being able to make it blank.Any ideas guys?Cheers
<SCRIPT language=Javascript>
window.addEventListener("load", function () {
document.getElementById("quantity").addEventListener("keyup", function (evt) {
var target = evt.target;
target.value = target.value.replace(/[^\d]/, "");
if (parseInt(target.value, 10) > <%=dvd5.getQuantityInStock()%>) {
target.value = target.value.slice(0, target.value.length - 1);
}
}, false);
});
<form action="RegServlet" method="post"><p>Enter quantity you would like to purchase :
<input name="quantity" id="quantity" size=15 type="text" value="1" />
You could use your onkeyup listener to check if the input's value is empty. Something along the lines of:
if(target.value == null || target.value === "")
target.value = 1;
}
You could add a function to validate the form when the text box loses focus. I ported the following code at http://forums.asp.net/t/1660697.aspx/1, but it hasn't been tested:
document.getELementById("quantity").onblur = function validate() {
if (document.getElementById("quantity").value == "") {
alert("Quantity can not be blank");
document.getElementById("quantity").focus();
return false;
}
return true;
}
save the text when keydown
check empty when keyup, if empty, restore the saved text, otherwise update the saved text.
And you could try the new type="number" to enforce only number input
See this jsfiddle

Categories

Resources