so i have a password and confirm password and I obviously need to match and show a message if not match.
my requirements:
the message should only show after the confirm password (second input)input.
my setup now is, when user blur out confirm password(second input) the function runs and throw err message if no match and also is dynamically hidden when user type the correct password (used onkeyup) that matches password input (first input)
problem:
if the user go back and change the first input no message is shown. if I use the same onblur function on password (first input), then the message shows before I input anything in the second field (confirm password). how do i fix this?
$onInit = () => {
let self = this;
this.siRole.getRoles().then((roleList) => {
self.roleList = roleList.filter((r) => {return !r.hidden});
}, (err) => {
self.siAlertDialog.error(err.message);
})
this.hide = true;
}
passwordWatchOnblur = ()=>{
this.hide = this.newUser.password == this.newUser.confirmPassword ? true :false
}
passwordWatchOnkeyup = ()=>{
if(this.newUser.password == this.newUser.confirmPassword){
this.hide=true;
}
}
<div layout layout-xs='column'>
<md-input-container flex class="md-accent">
<label translate="LABELS.PASSWORD"></label>
<input ng-model='$ctrl.newUser.password' type='password' required/>
</md-input-container>
<md-input-container flex class="md-accent">
<label translate="LABELS.CONFPASS"></label>
<input id="confirm" ng-model='$ctrl.newUser.confirmPassword' type='password' ng-blur="$ctrl.passwordWatchOnblur()" ng-keyup="$ctrl.passwordWatchOnkeyup()" required/>
<span ng-hide="$ctrl.hide" class='label-error'>{{'SI-MESSAGES.PASS-NO-MATCH'|translate}}</span>
</md-input-container>
</div>
Possible solution:
Use the same onkeyup function on password (first input) and modify passwordWatchOnkeyup like tihs:
passwordWatchOnkeyup = () => {
this.hide = typeof this.newUser.confirmPassword === 'undefined' || this.newUser.confirmPassword === null || this.newUser.password == this.newUser.confirmPassword;
}
Why: If there is no confirmPassword or they both are equal, then hide message.
UPDATE (added alternative for passwordWatchOnblur function)
... or you can use this (passwordWatchOnblur) function on the onblur on password (first input)
passwordWatchOnblur = () => {
this.hide = typeof this.newUser.confirmPassword === 'undefined' || this.newUser.confirmPassword === null || this.newUser.password == this.newUser.confirmPassword;
}
P.S.: The content of the functions are the same. What changes is the time where they are called. With the passwordWatchOnblur being called on the onblur the message will not be shown until the user has left the input, and not while he/she is typing the password.
Related
I'm working on a asp.net MVC project. On one page, it has many controls and features. When user clicks 'submit' button, it will do many validations in the controller for the input. If something is not right, it will show the error on the page. Otherwise, will save the data in the database with a Guid, and go to the next page.
The problem is: the validation takes some time, user may accidentally click the submit button more than once which results in saving data to the database with the same Guid, which throws an error since Guid has to be unique for each data.
Is there a way to prevent user clicking more than once? We can not simply disable the button after click. If the validation has issue, then user can not submit again since the button is disabled.
You can disable the submit button until all the validation has been completed. Track a variable for each conditional that returns true when the validation for that section of the form is complete and then check each of these variables at the end to make sure each one is true. If they are all true set the submit.disabled to false.
NOTE: You can do this with each input as well, disabling each input until the previous input has been properly validated.
Below is a very rudimentary example of this logic.
const submit = document.getElementById('submit')
const fname = document.getElementById('fname')
const lname = document.getElementById('lname')
const email = document.getElementById('email')
const inputs = document.querySelectorAll('.input')
function emailIsValid(email) {
return /^[^\s#]+#[^\s#]+\.[^\s#]+$/.test(email)
}
function nameIsValid(name) {
return name.match(/^[A-Za-z]+$/)
}
function validate(fname, lname, email, submit) {
// the validation variables to check at end to set submit.disabled to false
let fnameCheck = false,
lnameCheck = false,
emailCheck = false;
// check first name field
if (fname.value !== '' && fname.value.length > 1 && nameIsValid(fname.value)) {
fname.style.background = 'lightgreen'
fname.previousSibling.previousSibling.style.background = 'green'
fnameCheck = true
} else {
// JIC they delete reset to false
fnameCheck = false
fname.style.background = 'pink'
}
if (lname.value !== '' && lname.value.length > 2 && nameIsValid(fname.value)) {
lnameCheck = true
lname.style.background = 'lightgreen'
} else {
lnameCheck = false
lname.style.background = 'pink'
}
if (emailIsValid(email.value)) {
emailCheck = true
email.style.background = 'lightgreen'
} else {
emailCheck = false
email.style.background = 'pink'
}
// log for visual inspection of check-variable values
console.log(lnameCheck, fnameCheck, emailCheck)
// make sure all check-variables are set to true
if (fnameCheck === true && lnameCheck === true && emailCheck === true) {
submit.disabled = false
}
}
// event listener for each input on input field run the validate function
// and pass in our inputs and submit button for manipulation.
inputs.forEach(input =>
input.addEventListener('input', () => validate(fname, lname, email, submit))
)
<form action="#">
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" class="input"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" class="input"><br>
<label for="email">email:</label><br>
<input type="text" id="email" name="email" class="input"><br>
<input type="submit" id="submit" value="Submit" disabled>
</form>
I am trying to create a 2 part login, 1st part where you enter the username, click login, and the login takes you to a page where you enter your password. I have a js function where I check if the username field is null, because I want to require the user to enter something in the text field before clicking the button redirects them to the second part of the login. However, I am getting an error: Uncaught ReferenceError: loginCheck is not defined at HTMLInputElement.onclick
here is my code
var formhtml = '<div class="container"><label for="userNameBox"><b>Username </b></label><input type="text" id="userNameBox" placeholder="Enter Username" required ="required"><br></br> <input type="button" id ="loginButton" value="Login"onclick="javascript:loginCheck()"/></div>'
function loginCheck(){
var x = null;
if(document.getElementById("userNameBox").value !=null){
document.getElementById("loginButton").onclick = function () {
location.href = "myLogin.Part2";
}
}
else{
alert("username required");
location.reload();
}
}
$('.login').click(function(e)
{
e.preventDefault();
if ($('#loginbox').html() == '')
$('#loginbox').html(formhtml);
$('#loginbox').show();
return false;
});
You seem to be mixing a lot of Vanilla JavaScript and jQuery. Although that's not wrong, it might help you with development by choosing one or the other.
Like #Teemu said, the value of an input is never null. If it is empty than the value will be represented as an empty string "".
The loginCheck function will add an event listener to the loginButton element. But that element already has an onclick attribute which calls the loginCheck function. This will not run as you would like it to. Instead of both add an event listener with either addEventListener (Vanilla JavaScript) or with the on method (jQuery)
I've tried to convert your code so that it uses jQuery. Check it out and let me know if your problem has been resolved.
const $document = $(document);
const $login = $("#login");
const $loginBox = $("#loginbox");
const $formElement = $(`
<div class="container">
<label for="userNameBox"><b>Username </b></label>
<input type="text" id="userNameBox" placeholder="Enter Username" required="required"><br>
<input type="button" id="loginButton" value="Login"/>
</div>
`);
$document.on("click", "#loginButton", function() {
const $userNameBox = $("#userNameBox");
if ($userNameBox.val() !== "") {
location.href = "myLogin.Part2";
} else {
alert("username required");
location.reload();
}
});
$login.on("click", function (event) {
if ($loginBox.children().length === 0) {
$loginBox.append($formElement);
}
$("#loginbox").show();
event.preventDefault();
return false;
});
I have to make a HTML page, with a form containing an email address and a URL. I should check whether the email is a legitimate Gmail or Yahoo! format, and if the URL is correct as well. However, on Chrome, when I type a wrong email, then without correcting it I click into the URL's input, I get infinite alert messages.
Here's the HTML file
<form action="/index.html" method="POST" name="form">
<p>Full name: <input type="text" pattern="[A-Z][a-z]+ [A-Z][a-z]+"></p>
<p>Date: <input type="date"></p>
<p>Email: <input type="email" id="email" onblur="validateEmail(document)"></p>
<p>Favourite website: <input type="url" id="url" onblur="validateFavURL(document)"></p>
</form>
And heres the JS file:
function validateEmail(document) {
let email = document.getElementById("email").value
let regexGmail = /\S+#gmail\.\S+/
let regexYahoo = /\S+#yahoo\.\S+/
if (!regexGmail.test(email) || regexYahoo.test(email)) {
alert("Incorrect email address!")
}
}
function validateFavURL(document) {
let url = document.getElementById("url").value
let regexURL = /https?:\/\/www\.[A-Za-z1-9_-]+\.[A-Za-z1-9_-]+\.[A-Za-z1-9_-]+/
let regextwodots = /^((?!\.\.).)+/
let regexdots = /\..+\./
if (!regexURL.test(url) || !regextwodots.test(url) || regexdots.test(url)) {
alert("Incorrect webpage!")
}
}
I have changed some of your code and added some of mine, now the alert will be triggered with smart.
/*
hasAlreadyAlerted is a boolean variable, from it's name you know that
this variable will be false only if the elementy currently focusing on
has not been alerted last time.
alwertedElement is a reference to the last element that triggered the alert
*/
var hasAlreadyAlerted = false, alertedElement;
document.querySelector("form").addEventListener('focus', (event) =>
hasAlreadyAlerted = event.target == alertedElement, true);
function validateEmail(emailElement) {
let email = emailElement.value,
regexGmail = /\S+#gmail\.\S+/,
regexYahoo = /\S+#yahoo\.\S+/;
if(!hasAlreadyAlerted && (!regexGmail.test(email) || regexYahoo.test(email))) {
hasAlreadyAlerted = true;
alertedElement = emailElement;
alert("Incorrect email address!")
}
}
function validateFavURL(urlElement) {
let url = urlElement.value,
regexURL = /https?:\/\/www\.[A-Za-z1-9_-]+\.[A-Za-z1-9_-]+\.[A-Za-z1-9_-]+/,
regextwodots = /^((?!\.\.).)+/,
regexdots = /\..+\./;
if (!hasAlreadyAlerted && (!regexURL.test(url) || !regextwodots.test(url) || regexdots.test(url))) {
hasAlreadyAlerted = true;
alertedElement = document.getElementById("url");
alert("Incorrect webpage!")
}
}
/*
So if the user types a wrong email or url that triggers the alert and
stores the reference of the element and that an alert has already triggerd,
and no other alerts should be triggered from the same element unless the user
has clicked in another one, this is all to avoid getting in an infinite loop
like you have already seen, and the cause of that loop is just the way the
events are being handled, I thinks when the user types something and clicks
outside the input element the blur event is triggered and that triggers an
alert and once you click on the alert button the blur event is triggered once
again and so on making a an infinite number of alerts
*/
<form action="/index.html" method="POST" name="form">
<p>Full name: <input type="text" pattern="[A-Z][a-z]+ [A-Z][a-z]+"></p>
<p>Dátum: <input type="date"></p>
<p>Email: <input type="email" id="email" onblur="validateEmail(this)"></p>
<p>Kedvenc weboldal: <input type="url" id="url" onblur="validateFavURL(this)"></p>
</form>
I have text box in my page, which i can enter 9 digit number. Onblur I am validating like the entered number is valid or not using API call, If service returns failure it will clear the text box with red border and form will be invalid. The event conflict happening between OnBlur and Submit. Submit service will call only the form is valid otherwise it will show toaster like enter mandatory filed.
If the text field focused and directly if I click on submit button, both event calling simultaneously and it is clearing the number field OnBlur as well as the service is calling.
Please can you help me to resolve this conflicts.
file.html
<form class="contact-form" #create="ngForm">
<div class="controls">
<input NumberOnly="true" type="text" id="num" [ngClass]="{'red-border-class': ((showErrorFlag == true && numberField.errors) || (showErrorFlag == true && numberField.errors && (numberField.dirty || numberField.touched)))}"
[disabled]="disableRotaDetailFields" [(ngModel)]="number"
class="floatLabel" name="ownership" required #numberField="ngModel" (blur)="validatenumber(number)" [maxLength]="einLength">
<label for="ein">number<sup>*</sup></label>
</div>
<button (click)="SaveData(create)">Save</button>
</form>
file.ts
public validatenumber(number) {
let reqObj = {
"ownership": number
}
this.calloutService.validateOwnerEin(reqObj)
.pipe(takeUntil(this.unsubscribe))
.subscribe((data) => {
}, (err) => {
if (err.status == 404) {
this.number = "";
}
this.toastr.error(err.overriddenMessage);
})
}
SaveData(){
if (!formFlag.valid ) {
this.showErrorFlag = true;
this.toastr.error('Please fill all the mandatory fields');
}else {
this.calloutService.createData(this.data)
.pipe(takeUntil(this.unsubscribe))
.subscribe(data => {
this.showSpinnerFlag = false;
let response = data;
if (data) {
this.toastr.success("Rota created successfully.");
} else {
this.toastr.error("Could not save.");
}
}, err => {
this.showSpinnerFlag = false;
this.toastr.error(err.overriddenMessage);
})
}
}
I have a form to change the personal details of the user. In this form I allow the user to change their email and/or password. With jQuery I want to show a 'Current Password' field when it detects that one of these fields is changed.
For the email field this means that when it is changed the password field appears, but when the email is re-entered correctly it hides itself again.
For the password field this means it simply shows when anything is typed inside the field.
I got the basics working, but I can't get them to work with each other. So when I change both and change one back, the Current Password field hides itself.
let requiredSet;
$('.js-show-target-on-change').on('input', function() {
const target = $('.js-show-target-on-change__target');
let currentValue = $(this).val();
if ( $(this).data('type') === 'email' ) {
const emailValue = $(this).data('value');
if ( currentValue !== emailValue && !requiredSet === true ) {
target.show();
target.find('input').prop('required', true);
requiredSet = true;
} else if ( currentValue === emailValue ) {
target.hide();
target.find('input').prop('required', false);
requiredSet = false;
}
} else {
if ( !requiredSet === true ) {
target.show();
target.find('input').prop('required', true);
requiredSet = true;
} else if ( !currentValue.length ) {
target.hide();
target.find('input').prop('required', false);
requiredSet = false;
}
}
});
JsFiddle
Would love some help with this since I've been stuck for so long... Thanks in advance!
EDIT: Here's a description of how the code works:
cost email = $('#email').val() // get the starting value of the email
// field to check if it has changed
$('.js-show-target-on-change').on('input', function(){
const f = $('#email').val() !== email
// check if the old email value is different than the new email value
|| $('#newPassword').val().length > 0
// check if there is text in the new password field
? 'show' : 'hide';
// if one of the above statements are true,show the field, else hide it
$('.js-show-target-on-change__target')[f]();
// update the field based on the above condition
});
If I understood your use case correctly the following code should do the job:
const email = $('#email').val();
$('.js-show-target-on-change').on('input', function() {
const f = $('#email').val() !== email || $('#newPassword').val().length > 0 ? 'show' : 'hide';
$('.js-show-target-on-change__target')[f]();
});
Use an attribute to specify the input value has been changed and later use that attribute to toggle the visibility of the input element.
$('.js-show-target-on-change').on('input', function() {
const target = $('.js-show-target-on-change__target');
let currentValue = this.value;
// if input is email
if (this.id === 'email') {
// get default value
let defValue = $(this).data('value');
// set attribute value based on old and default value
$(this).attr('data-changed', defValue !== currentValue);
} else {
// if password field then set attribute based on length
$(this).attr('data-changed', currentValue.length > 0);
}
// check number of changed fields
let visible = $('input[data-changed="true"]').length > 0;
// toggle based on the value
target.toggle(visible);
target.find('input').prop('required', visible);
});
$('.js-show-target-on-change').on('input', function() {
const target = $('.js-show-target-on-change__target');
let currentValue = this.value;
// if input is email
if (this.id === 'email') {
// get default value
let defValue = $(this).data('value');
// set attribute value based on old and default value
$(this).attr('data-changed', defValue !== currentValue);
} else {
// if password field then set attribute based on length
$(this).attr('data-changed', currentValue.length > 0);
}
// check number of changed fields
let visible = $('input[data-changed="true"]').length > 0;
// toggle based on the value
target.toggle(visible);
target.find('input').prop('required', visible);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form method="post" accept-charset="UTF-8" enctype="multipart/form-data" class="c-form">
<div class="c-form__row">
<label class="c-form__label" for="email">Email</label>
<div class="c-form__field">
<div class="c-input__control">
<input required class="c-input js-show-target-on-change" data-type="email" type="email" id="email" name="email" value="info#johndoe.com" data-value="info#johndoe.com">
</div>
</div>
</div>
<div class="c-form__row">
<label class="c-form__label" for="newPassword">New password</label>
<div class="c-form__field">
<div class="c-input__control">
<input class="c-input js-show-target-on-change" type="password" id="newPassword" name="newPassword">
</div>
</div>
</div>
<div class="c-form__row js-show-target-on-change__target" style="display: none;">
<label class="c-form__label" for="currentPassword">
Current password
<span class="u-warning">(required to change email or password)</span>
</label>
<div class="c-form__field">
<div class="c-input__control">
<input class="c-input" type="password" id="currentPassword" name="password">
</div>
</div>
</div>
<div class="c-form__submit">
<button class="c-button c-button--fullwidth" type="submit">Save</button>
</div>
</form>