I have a form with HTML validations and I am using JS to add or remove error style.
<form action="" id="addForm">
<div>
<label for="name">Name</label>
<input type="text" id="name" name="name" required minlength="3" />
</div>
<button type="submit">Add</button>
</form>
window.onload = handleLoad;
function handleLoad() {
const form = document.forms.addForm;
const name = form.name;
name.onkeyup = function () {
if (name.checkValidity()) {
name.classList.remove("error");
} else {
name.classList.add("error");
}
};
}
In this case the error class gets applied as the user is typing in the field. Is there a way to prevent this?
You are using the onkeyup event, which means the event is triggered every time the user releases a key.
If you want to check the input field only when the user moves to the next field, you could use the onfocusout event.
name.onkeyup = function () {
if (name.checkValidity()) {
name.classList.remove("error");
} else {
name.classList.add("error");
}
}
P.S., If you have a small form, you could also implement validation when the submit button is clicked.
I cannot figure out how to pass an HTML input to a JS variable.
<form id="form" target="_self">
<input type="text" id="task" placeholder="What's on the agenda?" onsubmit="getForm()">
</form>
My HTML form with the function being called as follows:
function getForm() {
var form = document.getElementById("task").value;
console.log(form);
}
However, when I press enter after typing into the input text, it just refreshes the page and changes the URL from index.html to index.html?task=foo and doesn't log anything in the console.
Try this:
<form id="form" onsubmit="getForm()" target="_self">
<input id="task" placeholder="What's on the agenda?" type="text">
</form>
and
function getForm(event) {
event.preventDefault();
var form = document.getElementById("task").value;
console.log(form);
}
…but keep in mind that you need at least a button or an input to submit the form.
There are two issues with the OP's code.
The getForm function will not execute because onsubmit is wired up against the input element instead of the form element. HTMLInputElement doesn't emit submit events.
The default action of a form is to submit the form to the server, so even if the getForm function were correctly wired up it would execute quickly and then the page would refresh. Likely you want to prevent that default action.
Generally speaking, it's good practice to wire up event listeners in your JavaScript code. Here's a snippet that demonstrates working code akin to what the OP is attempting.
'use strict';
const taskFrm = document.getElementById('taskFrm');
const taskTxt = document.getElementById('taskTxt');
taskFrm.addEventListener('submit', e => {
e.preventDefault();
console.log(taskTxt.value);
});
<form id="taskFrm">
<input id="taskTxt" placeholder="What's on the agenda?">
</form>
For the sake of completeness, if you want to wire up the onsubmit function in the HTML, here's how:
function getForm(e) {
var form = document.getElementById("task").value;
console.log(form);
e.preventDefault(); // Or return false.
}
<form id="form" target="_self" onsubmit="getForm(event)">
<input type="text" id="task" placeholder="What's on the agenda?">
</form>
I have a login form on a modal jquery dialog with the usual 2 text INPUTs. When I enter a login name and password then click the submit, the call back function is called.
The first thing the callback does is try to extract the values of the two INPUTs, but the values returned are empty strings (I have a breakpont here, and have even stepped through the jquery processing of the objects - they objects are correctly identified as the fields on the form, but value="" for both).
At this point I can still see the values in the form, and when the callback exits and the focus goes back to the form, the values are still in the INPUTS. I also tried .prop("value") rather than .val(), but the result was the same.
I just can't figure why I can't read the values - any help appreciated.
<form id="cp-loginform" action="/cypo/index.php" method="POST" >
<input type="hidden" name="Login" value="Login">
<input type="hidden" name="pp" value="0" />
<input type="text" id="cp-loginname" name = "loginname" placeholder = "Login ID" class="loginforminput cp-width-50" autofocus >
<input type="password" id="cp-password" name = "password" placeholder = "password" class="loginforminput cp-width-50"></p>
<input type="submit" id="cp-submit" name = "submit" onclick="ProcessLogin()" ></p>
</form>
function ProcessLogin() {
var loginval = $("#cp-loginname").val();
var passwordval = $("#cp-password").val();
console.log(loginval.concat(" ",passwordval));
}
PROBLEM RESOLVED:
I felt that this was a scope issue. The form itself was obviously OK (if submitted from the dialog it worked) - it was just the attempt to check the INPUT values using jquery that wasn't working.
I found that my select had to start with the dialog element and include a descendent path to my INPUTs. It's as if the dialog puts a wrapper around the elements inside so they are no longer visible as owned by the document.
If I login with xxx and zzz and step therough the following code I see this:
var loginval = $("#cploginname").val(); << = ""
var passwordval = $("#cppassword").val(); << = ""
var loginval = $("#cp-loginform #cploginname").val(); << = ""
var passwordval = $("#cp-loginform #cppassword").val(); << = ""
var loginval = $("#cpdialog #cp-loginform #cploginname").val(); << = "xxx"
var passwordval = $("#cpdialog #cp-loginform #cppassword").val(); << = "zzz"
console.log(loginval.concat(" ",passwordval));
I can't say I understand what's going on, but I have a solution so I am happy. Thanks to all who answered.
FINAL WORD
Thanks to #CMedina, I now understand. The form was defined in a hidden DIV at the top of my BODY section, and I passed $("#loginform") to a f() that created the dialog. The dialog was added to the DOM just before the . I had missed the fact that my original form was still in the DOM, so I was referencing that, not the dialog copy. When I included the dialog wrapper in the path, I finally 'found' the second copy.
Your button is the type submit (their natural behavior is to send the form). Remove the onclick in your button html.
<input type="submit" id="cp-submit" name = "submit">
You must add preventDefault to prevent submit the form and do what you want. Add the code JS for the button onclick event
$("#cp-submit").on("click", function(e){
e.preventDefault();
var loginval = $("#cp-loginname").val();
var passwordval = $("#cp-password").val();
console.log(loginval.concat(" ",passwordval));
});
Result: https://jsfiddle.net/cmedina/svjqb2a4/
Try it :
<html>
<head>
</head>
<body>
<form id="cp-loginform" action="/cypo/index.php" method="POST">
<input type="hidden" name="Login" value="Login">
<input type="hidden" name="pp" value="0" />
<input type="text" id="cp-loginname" name = "loginname" placeholder = "Login ID" class="loginforminput cp-width-50" autofocus >
<input type="password" id="cp-password" name = "password" placeholder = "password" class="loginforminput cp-width-50">
<input type="submit" id="cp-submit" name ="submit" onclick="ProcessLogin(event)">
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
function ProcessLogin(e) {
e.preventDefault();
var loginval = $("#cp-loginname").val();
var passwordval = $("#cp-password").val();
alert(loginval.concat(" ",passwordval));
}
</script>
</body>
</html>
learning Angular, met another issue in my way, hope anyone can help.
I've got one button that must perform two actions: download something and send formdata to the server. So I've wrote this:
<form id='download'>
<label for='name'>Name:</label>
<input type='name' ng-model='nameValue'>
<label for='email'>Email:</label>
<input type='email' id='email' ng-model='emailValue'>
</form>
<a ng-click='sendFormDataIfVal()' href="{{filename}}" download="{{filename}}">Download</a>
But the problem and my question is - now downloading and sending occur simultaneously while I wanna download file only if emailValue pass validation and nameValue is not empty. Suppose it's gonna be something like this, but I dunno how to complete function
$scope.sendFormDataIfVal = function() {
$scope.validateEmail() && $scope.sendFormData(); // download & send
if(!$scope.validateEmail()) {
// do not download and do not send
}
};
Any advise will be greatly... u know :)
One approach is to disable the link using css.
once enabled, both the click event handler and the native download function will work.
toggle the link's 'disabled' css class via a validation function
here is a working example
HTML
<body ng-app="myApp" ng-controller="myController">
<form id="download">
<label for="name">Name:</label>
<input type="name" ng-model="nameValue" />
<label for="email">Email:</label>
<input type="email" id="email" ng-model="emailValue" />
</form>
<a ng-class="{'disabled' : !isFormValid()}" ng-click="sendFormData()" ng-href="{{fileUrl}}" download="{{fileName}}" >Download</a>
</body>
JS
var myApp = angular.module('myApp',[]);
myApp.controller('myController', ['$scope', function($scope) {
$scope.emailValue = 'sample#email.com';
$scope.nameValue = "";
$scope.fileUrl = "http://thatfunnyblog.com/wp-content/uploads/2014/03/funny-videos-funny-cats-funny-ca.jpg";
$scope.fileName = "funny-cat.jpeg";
$scope.isEmailValid = function(){
//replace this simplified dummy code with actual validation
return $scope.emailValue.indexOf('#') !== -1;
}
$scope.isFormValid = function(){
return $scope.isEmailValid() && $scope.nameValue.length;
}
$scope.sendFormData = function(){
console.log('sent that data');
}
}]);
CSS
a.disabled{
/*simulate disabled using css, since this property is nto supported on anchor element*/
color:gray;
pointer-events:none;
}
Try this:
$scope.sendFormDataIfVal = function() {
if(!$scope.validateEmail()) {
// do not download and do not send
}
else{
download and send
}
};
I've got the following HTML form: http://jsfiddle.net/nfgfP/
<form id="form" onsubmit="return(login())">
<input name="username" placeholder="Username" required />
<input name="pass" type="password" placeholder="Password" required/>
<br/>Remember me: <input type="checkbox" name="remember" value="true" /><br/>
<input type="submit" name="submit" value="Log In"/>
Currently when I hit enter when they're both blank, a popup box appears saying "Please fill out this field". How would I change that default message to "This field cannot be left blank"?
The type password field's error message is simply *****. To recreate this give the username a value and hit submit.
Here is some code to display a custom error message:
<input type="text" id="username" required placeholder="Enter Name"
oninvalid="ths.setCustomValidity('Enter User Name Here')"
oninput="setCustomValidity('')"/>
This part is important because it hides the error message when the user inputs new data:
oninput="setCustomValidity('')"
Note: the this keyword is not required for inline event handlers, but you may want to use it anyway for consistency.
Use setCustomValidity:
document.addEventListener("DOMContentLoaded", function() {
var elements = document.getElementsByTagName("INPUT");
for (var i = 0; i < elements.length; i++) {
elements[i].oninvalid = function(e) {
e.target.setCustomValidity("");
if (!e.target.validity.valid) {
e.target.setCustomValidity("This field cannot be left blank");
}
};
elements[i].oninput = function(e) {
e.target.setCustomValidity("");
};
}
})
I changed to vanilla JavaScript from Mootools as suggested by #itpastorn in the comments, but you should be able to work out the Mootools equivalent if necessary.
If setCustomValidity is set to anything other than the empty string it will cause the field to be considered invalid; therefore you must clear it before testing validity, you can't just set it and forget.
As pointed out in #thomasvdb's comment below, you need to clear the custom validity in some event outside of invalid otherwise there may be an extra pass through the oninvalid handler to clear it.
It's very simple to control custom messages with the help of HTML5 event oninvalid
Here is code:
<input id="UserID" type="text" required="required"
oninvalid="this.setCustomValidity('Witinnovation')"
onvalid="this.setCustomValidity('')">
This is most important:
onvalid="this.setCustomValidity('')"
Note: This no longer works in Chrome, not tested in other browsers. See edits below. This answer is being left here for historical reference.
If you feel that the validation string really should not be set by code, you can set you input element's title attribute to read "This field cannot be left blank". (Works in Chrome 10)
title="This field should not be left blank."
See http://jsfiddle.net/kaleb/nfgfP/8/
And in Firefox, you can add this attribute:
x-moz-errormessage="This field should not be left blank."
Edit
This seems to have changed since I originally wrote this answer. Now adding a title does not change the validity message, it just adds an addendum to the message. The fiddle above still applies.
Edit 2
Chrome now does nothing with the title attribute as of Chrome 51. I am not sure in which version this changed.
It's very simple to control custom messages with the help of the HTML5 oninvalid event
Here is the code:
User ID
<input id="UserID" type="text" required
oninvalid="this.setCustomValidity('User ID is a must')">
By setting and unsetting the setCustomValidity in the right time, the validation message will work flawlessly.
<input name="Username" required
oninvalid="this.setCustomValidity('Username cannot be empty.')"
onchange="this.setCustomValidity('')" type="text" />
I used onchange instead of oninput which is more general and occurs when the value is changed in any condition even through JavaScript.
I have made a small library to ease changing and translating the error messages. You can even change the texts by error type which is currently not available using title in Chrome or x-moz-errormessage in Firefox. Go check it out on GitHub, and give feedback.
It's used like:
<input type="email" required data-errormessage-value-missing="Please input something">
There's a demo available at jsFiddle.
Try this one, its better and tested:
function InvalidMsg(textbox) {
if (textbox.value === '') {
textbox.setCustomValidity('Required email address');
} else if (textbox.validity.typeMismatch){
textbox.setCustomValidity('please enter a valid email address');
} else {
textbox.setCustomValidity('');
}
return true;
}
<form id="myform">
<input id="email"
oninvalid="InvalidMsg(this);"
oninput="InvalidMsg(this);"
name="email"
type="email"
required="required" />
<input type="submit" />
</form>
Demo:
http://jsfiddle.net/patelriki13/Sqq8e/
The easiest and cleanest way I've found is to use a data attribute to store your custom error. Test the node for validity and handle the error by using some custom html.
le javascript
if(node.validity.patternMismatch)
{
message = node.dataset.patternError;
}
and some super HTML5
<input type="text" id="city" name="city" data-pattern-error="Please use only letters for your city." pattern="[A-z ']*" required>
The solution for preventing Google Chrome error messages on input each symbol:
<p>Click the 'Submit' button with empty input field and you will see the custom error message. Then put "-" sign in the same input field.</p>
<form method="post" action="#">
<label for="text_number_1">Here you will see browser's error validation message on input:</label><br>
<input id="test_number_1" type="number" min="0" required="true"
oninput="this.setCustomValidity('')"
oninvalid="this.setCustomValidity('This is my custom message.')"/>
<input type="submit"/>
</form>
<form method="post" action="#">
<p></p>
<label for="text_number_1">Here you will see no error messages on input:</label><br>
<input id="test_number_2" type="number" min="0" required="true"
oninput="(function(e){e.setCustomValidity(''); return !e.validity.valid && e.setCustomValidity(' ')})(this)"
oninvalid="this.setCustomValidity('This is my custom message.')"/>
<input type="submit"/>
</form>
I have a simpler vanilla js only solution:
For checkboxes:
document.getElementById("id").oninvalid = function () {
this.setCustomValidity(this.checked ? '' : 'My message');
};
For inputs:
document.getElementById("id").oninvalid = function () {
this.setCustomValidity(this.value ? '' : 'My message');
};
Okay, oninvalid works well but it shows error even if user entered valid data. So I have used below to tackle it, hope it will work for you as well,
oninvalid="this.setCustomValidity('Your custom message.')" onkeyup="setCustomValidity('')"
If your error message is a single one, then try below.
<input oninvalid="this.setCustomValidity('my error message')"
oninput="this.setCustomValidity('')"> <!-- 👈 don't forget it. -->
To handle multiple errors, try below
<input oninput="this.setCustomValidity('')">
<script>
inputElem.addEventListener("invalid", ()=>{
if (inputElem.validity.patternMismatch) {
return inputElem.setCustomValidity('my error message')
}
return inputElem.setCustomValidity('') // default message
})
</script>
Example
You can test valueMissing and valueMissing.
<form>
<input pattern="[^\\/:\x22*?<>|]+"
placeholder="input file name"
oninput="this.setCustomValidity('')"
required
>
<input type="submit">
</form>
<script>
const form = document.querySelector("form")
const inputElem = document.querySelector(`input`)
inputElem.addEventListener("invalid", ()=>{
if (inputElem.validity.patternMismatch) {
return inputElem.setCustomValidity('Illegal Filename Characters \\/:\x22?<>|')
}
return inputElem.setCustomValidity('') // return default message according inputElem.validity.{badInput, customError, tooLong, valueMissing ...}
})
form.onsubmit = () => {
return false
}
</script>
ValidityState
const username= document.querySelector('#username');
const submit=document.querySelector('#submit');
submit.addEventListener('click',()=>{
if(username.validity.typeMismatch){
username.setCustomValidity('Please enter User Name');
}else{
username.setCustomValidity('');
}
if(pass.validity.typeMismatch){
pass.setCustomValidity('Please enter Password');
}else{
pass.setCustomValidity('');
}
})
Adapting Salar's answer to JSX and React, I noticed that React Select doesn't behave just like an <input/> field regarding validation. Apparently, several workarounds are needed to show only the custom message and to keep it from showing at inconvenient times.
I've raised an issue here, if it helps anything. Here is a CodeSandbox with a working example, and the most important code there is reproduced here:
Hello.js
import React, { Component } from "react";
import SelectValid from "./SelectValid";
export default class Hello extends Component {
render() {
return (
<form>
<SelectValid placeholder="this one is optional" />
<SelectValid placeholder="this one is required" required />
<input
required
defaultValue="foo"
onChange={e => e.target.setCustomValidity("")}
onInvalid={e => e.target.setCustomValidity("foo")}
/>
<button>button</button>
</form>
);
}
}
SelectValid.js
import React, { Component } from "react";
import Select from "react-select";
import "react-select/dist/react-select.css";
export default class SelectValid extends Component {
render() {
this.required = !this.props.required
? false
: this.state && this.state.value ? false : true;
let inputProps = undefined;
let onInputChange = undefined;
if (this.props.required) {
inputProps = {
onInvalid: e => e.target.setCustomValidity(this.required ? "foo" : "")
};
onInputChange = value => {
this.selectComponent.input.input.setCustomValidity(
value
? ""
: this.required
? "foo"
: this.selectComponent.props.value ? "" : "foo"
);
return value;
};
}
return (
<Select
onChange={value => {
this.required = !this.props.required ? false : value ? false : true;
let state = this && this.state ? this.state : { value: null };
state.value = value;
this.setState(state);
if (this.props.onChange) {
this.props.onChange();
}
}}
value={this && this.state ? this.state.value : null}
options={[{ label: "yes", value: 1 }, { label: "no", value: 0 }]}
placeholder={this.props.placeholder}
required={this.required}
clearable
searchable
inputProps={inputProps}
ref={input => (this.selectComponent = input)}
onInputChange={onInputChange}
/>
);
}
}
For a totaly custom check logic:
$(document).ready(function() {
$('#form').on('submit', function(e) {
if ($('#customCheck').val() != 'apple') {
$('#customCheck')[0].setCustomValidity('Custom error here! "apple" is the magic word');
$('#customCheck')[0].reportValidity();
e.preventDefault();
}
});
$('#customCheck').on('input', function() {
$('#customCheck')[0].setCustomValidity('');
});
});
input {
display: block;
margin-top: 15px;
}
input[type="text"] {
min-width: 250px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="form">
<input type="text" placeholder="dafault check with 'required' TAG" required/>
<input type="text" placeholder="custom check for word 'apple'" id="customCheck" />
<input type="submit">
</form>
Can be easily handled by just putting 'title' with the field:
<input type="text" id="username" required title="This field can not be empty" />