My issue is regarding jquery validation. I have a form and validation is working on input field but I am confused how to use the validation on the radio button because I have three radio buttons and the user can choose only one. All the radio button have their respected fields. I have to set the validation on it.
Example: I choose the first radio then the user should enter the book1 and book2 fields as well. If you choose the second radio then the user should enter the fruit1 and fruit2 fields value.
if user choose only radio button and without filling the fields details and clicked on submit then validation should display.
I tried some code. It's working for first radio button but what if any user chooses a second radio button?
This is the output I am getting.
Radio button Book is checked with Jquery validation if fields are empty
Notice here I choose fruit and clicked on submit button but validation is not displaying
The reason was I am not getting because I added only book radio button validation. Now how to use for fruit and subject?
book1: {required: true},
book2: {required: true}
$(document).ready(function() {
$("input[name='books_fruit_sub']").click(function() {
var test = $(this).val();
$(".show_fields").hide();
$("#show" + test).show();
});
$('#form').validate({ // initialize the plugin
rules: {
mobile: {
required: true,
number: true,
minlength: 10,
maxlength: 10
},
book1: {
required: true
},
book2: {
required: true
}
},
submitHandler: function(form) { // for demo
form.submit();
}
});
});
ul {
text-decoration: none;
margin: 0;
padding: 0;
}
ul li {
display: inline-block;
}
.error {
color: red;
}
<form action="" id="form">
<input type="text" name="mobile" placeholder="Mobile">
<ul>
<li>
<input type="radio" name="books_fruit_sub" id="books" value="books" checked>
<label for="books">Books</label>
</li>
<li>
<input type="radio" name="books_fruit_sub" id="fruit" value="fruit">
<label for="fruit">Fruit </label>
</li>
<li>
<input type="radio" name="books_fruit_sub" id="subject" value="subject">
<label for="subject">Subject </label>
</li>
</ul>
<div>
<div class="show_fields" id="showbooks">
<input type="text" name="book1" placeholder="Book 1">
<input type="text" name="book2" placeholder="Book 2">
</div>
<div class="show_fields" id="showfruit" style="display: none;">
<input type="text" name="fruit1" placeholder="Fruit 1">
<input type="text" name="fruit2" placeholder="Fruit 2">
</div>
<div class="show_fields" id="showsubject" style="display: none;">
<input type="text" name="subject1" placeholder="Subject 1">
<input type="text" name="subject2" placeholder="Subject 2">
</div>
</div>
<input type="submit" name="send" value="Submit">
</form>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.0/jquery.validate.min.js"></script>
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.0/additional-methods.js"></script>
Just use a function that return true or false depending on if the related radio buttton is selected or not.
book1: {
required: function() {
return $('#books').is(':checked');
}
},
book2: {
required: function() {
return $('#books').is(':checked');
}
},
fruit1: {
required: function() {
return $('#fruit').is(':checked');
}
},
fruit2: {
required: function() {
return $('#fruit').is(':checked');
}
},
..
To be consequent use the plural form "fruits" and "subjects" as you did for "books" for your radio-buttons.
Here is your modified and working code in plunker.
You don't need jQuery for that. Using ES20xx, data-attributes and css it's fairly easy to create your own form validation. Let's, just for fun, work out an example based on your code.
We need a function to determine the chosen value of a radio button, that's checkRadio in the snippet;
We need a function to show or hide fields belonging to a radio button choice, that's switchFieldsBasedOnRadioChoice in the snippet. That function is activated by clickHandling. We use the chosen value from checkRadio to identify div#show[chosen value]] to be able to show the right div containing the input elements belonging to the chosen value;
We need an Object containing some methods to check fields denoted in html by data-check and activated by the value of [data-check], it's called fieldChecks;
We need a handler function for the (submit) button which will check all fields denoted by [data-check] for field value validity and warn if the field value is not valid, that's checkValues, activated by clickHandling;
We also create a focusin-handler that removes warnings from a previous input values check if the user clicks on or focuses one of the form fields;
We use data-attributes and css to style and display the warning values. Every text-input is wrapped in a div. We use the css class .invalid for (input fields container)-div that to style the warnings on the containing input fields (if applicable).
Notes
the handlers (click, focusin) in this snippet use event delegation.
client side validation is never sufficient. You should always check the fields values server side too before handling them at the server.
see also
// check value of a radio button
const checkRadio = name => {
const isChecked =
Array.from(document.querySelectorAll(`[name='${name}']`))
.filter(rb => rb.checked);
return isChecked.length ? isChecked[0].value : null;
};
// validity checks for field values ([data-check])
const fieldChecks = {
mobile: value => {
const valueClean = value.replace(/[^\d]/g, "");
return {
cando: valueClean.length === 10,
instruction: "Invalid: need 10 digits, you can use spaces and '-'"
};
},
booksOrFruits: value => ({
cando: value.trim().length >= 5,
instruction: "Invalid: all fields ≥ 5 characters"
}),
};
// add event listeners
document.addEventListener("click", clickHandling);
document.addEventListener("focusin", removeWarnings);
// click handling delegate
function clickHandling(evt) {
const origin = evt.target;
if (origin.type === "radio") {
return switchFieldsBasedOnRadioChoice(origin);
} else if (origin.id === "validate") {
return checkValues();
}
}
// focusin handling delegate: remove warnings on focus
function removeWarnings() {
console.clear();
Array.from(document.querySelectorAll(".notvalid"))
.forEach( el => el.classList.remove("notvalid") );
}
// check all field values and warn for invalid values in required fields
function checkValues() {
console.clear();
const checks = Array.from(document.querySelectorAll("[data-check]"));
let cando = true;
checks.forEach( input => {
// check for existence of input.dataset.check
if (!fieldChecks[input.dataset.check]) {
throw new Error(
`You forgot to add '${input.dataset.check}' to fieldChecks!`
);
}
const parent = input.parentNode;
// don't check input values from parent class "show_fields hidden"
if (parent.classList.contains("show_fields")
&& parent.classList.contains("hidden")) {
return false;
}
// perform the check denoted by [data-check] from the input field
const fieldChck = fieldChecks[input.dataset.check](input.value);
// if invalid value, use css/data-attributes to style a warning
if (!fieldChck.cando) {
parent.classList.add("notvalid");
if (fieldChck && fieldChck.instruction) {
parent.dataset.instruction = fieldChck.instruction;
}
cando = false;
} else {
parent.classList.add("valid")
}
} );
// all fields checked out ok
if (cando) { console.log("you're ok"); }
}
// show input fields belonging to a chosen radio input field
function switchFieldsBasedOnRadioChoice(origin) {
Array.from(document.querySelectorAll(".show_fields"))
.forEach(v => v.classList.add("hidden"))
const chosenValue = checkRadio(origin.name);
document.querySelector(`#show${chosenValue}`)
.classList.remove("hidden");
}
body {
margin: 2em;
font: normal 12px/15px verdana, arial, sans-serif;
}
input[type=text] {
margin: 0.3em 0.3em 0 0;
padding: 2px 4px;
}
button {
margin-top: 0.3em;
}
/* fields originating from radio choice */
.show_fields {
display: table-row;
visibility: "visible";
opacity: 1;
transition: opacity ease-in 0.5s 0s;
}
.hidden {
opacity: 0;
transition: opacity ease-out 0.1s 0s;
visibility: collapse;
}
/* styling related to validation */
.notvalid input {
border: 1px solid red;
}
.notvalid[data-instruction]:after {
content: attr(data-instruction);
margin-left: 0.2em;
}
.notvalid ::placeholder {
color: red;
}
.valid:after {
font-weight: bold;
content: "\2714";
color: green;
}
.valid input {
color: green;
}
<ul>
<li>
<input type="radio" name="books_fruit_sub" id="books" value="books" checked>
<label for="books">Books</label>
</li>
<li>
<input type="radio" name="books_fruit_sub" id="fruit" value="fruit">
<label for="fruit">Fruit </label>
</li>
</ul>
<div data-required>
<input type="text" name="mobile" placeholder="mobile" data-check="mobile">
</div>
<div>
<input type="text" name="notrequired" placeholder="not required">
</div>
<div class="show_fields" id="showbooks">
<input type="text" name="book1" placeholder="Book 1" data-check="booksOrFruits">
<input type="text" name="book2" placeholder="Book 2" data-check="booksOrFruits">
</div>
<div class="show_fields hidden" id="showfruit">
<input type="text" name="fruit1" placeholder="Fruit 1" data-check="booksOrFruits">
<input type="text" name="fruit2" placeholder="Fruit 2" data-check="booksOrFruits">
</div>
<button id="validate">Check</button>
Remove the rule for book1 and book2 from validator initialization and in your click handler just add this
$(".show_fields").find("input").removeAttr("required");
$("#show" + test).find("input").attr("required" , "required");
Also in html add required attribute to both inputs book1 and book2
Related
I have a input field that takes numeric inputs. Then i have a button which display the number of divs as per that input. after displaying div there is two radio-box buttons (paired end and single end) if I select paired end then i want two file upload fields in each divs. and if i select single end then i want only one file upload fields in each div.
I have tried but fileupload fields working on only first div.
function CreateText() {
var text = `<div class="row border-top py-3">
<div class="col-md-3">
<label">sample name *</label></br>
<input type="sample" id="sample" name="sample[]">
</div>
<div class="col-md-3" style="display:none" id="showsingle">
<div class="form-group">
<label for="form_upload">Upload file *</label></br>
<input type="file" id="myFile" name="filename1[]">
</div>
</div>
<div class="col-md-3" style="display:none" id="showpair">
<div class="form-group">
<label for="form_upload">Upload file *</label></br>
<input type="file" id="myFile" name="filename2[]">
<label for="form_upload">Upload file *</label></br>
<input type="file" id="myFile" name="filename2[]">
</div>
</div>
<div class="col-md-3 d-grid">
<div class="form-group">
<button class="btn btn-danger remove_add_btn">Remove</button>
</div>
</div>
</div>`;
var textCount = document.getElementById('textInput').value;
var html = '';
for (var i = 0; i < $('#textInput').val(); i++) {
html = document.getElementById('divDynamicTexts').innerHTML;
document.getElementById('divDynamicTexts').innerHTML = html + text.replace('', i);
}
}
function onlyOne() {
let SradioBox = document.getElementById("singleradio"),
Sfileupload = document.getElementById("showsingle"),
PradioBox = document.getElementById("pairedradio"),
Pfileupload = document.getElementById("showpair");
if (SradioBox.checked == true) {
Sfileupload.style.display = "block",
Pfileupload.style.display = "none";
} else if (PradioBox.checked == true) {
Pfileupload.style.display = "block",
Sfileupload.style.display = "none";
} else {
Pfileupload.style.display = "none",
Sfileupload.style.display = "none";
}
};
$(document).ready(function() {
$(document).on('click', '.remove_add_btn', function(e) {
e.preventDefault();
let row_item = $(this).parent().parent().parent();
$(row_item).remove();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="text-center">
<input type="text" id="textInput" value="" />
<input type="button" id="" value="Create upload fields" onclick="CreateText();" />
<div class="col-md-4" id="filebutton">
<div class="form-group ">
<label for="form_need">Library Type *</label>
</br>
<div class="px-2">
<label for="myradio">Single end:</label>
<input type="radio" id="singleradio" name="check" onclick="onlyOne();">
<label for="myradio">Paired end:</label>
<input type="radio" id="pairedradio" name="check" onclick="onlyOne();">
</div>
</div>
</div>
</div>
<div id="divDynamicTexts"></div>
ID attributes must be unique. It would be better to remove the IDs altogether ( or change to dataset attributes perhaps ) and use a delegated event listener to process the various clicks related to the task of adding/removing dynamic elements.
In the code below all ID attributes were either removed entirely or changed to data-id type values.
To avoid the need to process different form file input fields at the server the file-input fields are named the same but have an index so can be identified more readily in PHP ( or whatever backend you have )
The delegated listener, because it is bound to the document, will work for all elements whether or not they are static or added dynamically and makes heavy use of the event.target property to help identify the element that invoked the event.
The label element was being used incorrectly previously. If the form-input is within the label then there is no need for the for="ID" syntax ( note that the ID should be the ID of the input element to which the label belongs! ) - as it was the label's appeared to have a for attribute which did not related to an element in the form!
Using querySelector and querySelectorAll you can easily identify nodes of interest within the DOM so button clicks or radio button selection can fire a query to find nodes that are relevant - thus simplifying the hiding/showing of the file input elements.
const strhtml = `
<div data-id="dynrow" class="row border-top py-3">
<div class="col-md-3">
<label>sample name *<input type="text" name="sample[]"></label>
</div>
<div class="col-md-3" style="display:none" data-id="single" data-role="file-field">
<div class="form-group">
<label>Upload file *<input type="file" name="filename[1]" /></label>
</div>
</div>
<div class="col-md-3" style="display:none" data-id="pair" data-role="file-field">
<div class="form-group ">
<label>Upload file *<input type="file" name="filename[1]" /></label>
<label>Upload file *<input type="file" name="filename[2]" /></label>
</div>
</div>
<div class="col-md-3 d-grid">
<div class="form-group">
<button class="btn btn-danger remove_add_btn" data-id='remove'>Remove</button>
</div>
</div>
</div>`;
const _radio = document.querySelectorAll('[type="radio"][data-id]');
const _bttn = document.querySelector('[type="button"][data-id="add"]');
const _div = document.querySelector('#divDynamicTexts');
const _input = document.querySelector('input[type="number"][data-id="textInput"]');
let choice = false;
let qty = false;
/*
Disable radio buttons and the "Create" button initially
and enable when changes are made in the correct sequence.
1: select quantity -> enable radio bttns
2: select single or double -> enable "create" bttn
3: click bttn, create as per radio selection
*/
_input.addEventListener('change', e => {
_radio.forEach(n => {
n.disabled = e.target.value > 0 ? false : true;
});
qty=e.target.value;
});
document.addEventListener('click', e => {
if (e.target instanceof HTMLInputElement && e.target.dataset.id != null) {
/*
set global "choice" variable
and enable "Create" bttn.
*/
if (e.target.type == 'radio') {
choice = e.target.dataset.id;
_bttn.disabled = false;
}
}
/*
If the "choice" has been made the radio
buttons will be enabled. Based on radio
button selected create new HTML and then
unhide the appropriate single/pair DIV
element
*/
if (choice && qty > 0 && e.target.type == 'button') {
_div.innerHTML = '';
for (let i = 0; i < qty; i++) _div.insertAdjacentHTML('afterbegin', strhtml);
let expr = `div[data-id="${choice}"]`;
document.querySelectorAll(expr).forEach(n => n.style.display = 'block');
}
/*
unchanged: delete DIV & contents when "Remove" bttn is clicked.
*/
if (e.target instanceof HTMLButtonElement && e.target.dataset.id != null) {
if (e.target.dataset.id == 'remove') {
_div.removeChild(e.target.closest('[data-id="dynrow"]'));
}
}
});
body {
font-family: arial;
}
label {
display: block;
}
.px-2 {
display: inline-block;
}
.px-2 label {
display: inline-block;
margin: 0.5rem;
}
h2 {
font-size: 1.1rem;
margin: 1rem 0 0 0;
display: inline-block;
width: auto;
}
.inline {
display: inline;
margin: 0 1rem 0 0;
}
#divDynamicTexts {
min-height: 1rem;
margin: 2rem auto
}
div.row {
padding: 0.5rem;
border: 1px dotted grey;
margin: 0.5rem;
}
div[data-id='single'] .form-group label {
background: aliceblue
}
div[data-id='pair'] .form-group label {
background: lightsteelblue
}
div[data-id] .form-group label {
outline: 1px solid grey;
padding: 0.5rem;
margin: 0.5rem 0
}
.bold {
font-weight: bold
}
[disabled]{
border:1px solid red;
outline:2px solid red;
background:rgba(255,0,0,0.25);
}
<div class='text-center'>
<label class='inline bold'>Quantity:<input type='number' data-id='textInput' /></label>
<div class='col-md-4'>
<div class='form-group'>
<h2>Library Type</h2>
<div class='px-2'>
<label>Single end: <input type='radio' data-id='single' name='check' disabled /></label>
<label>Paired end: <input type='radio' data-id='pair' name='check' disabled /></label>
</div>
</div>
</div>
<input type='button' data-id='add' value='Create upload fields' disabled />
</div>
<div id='divDynamicTexts'></div>
I wrote the code below and I'm trying to change the input field background color the moment I type something. I have 4 input fields. If I click submit in the first time and any field is empty, the color of this field will change to red, but I need to change the color to green the moment I fill this empty field.
const submitButton = document.getElementById("submit")
const inputField = document.querySelectorAll(".input")
let requiredField = document.querySelectorAll(".requiredField")
inputField.forEach(function (item){
submitButton.addEventListener("click", function (){
if(item.value == '') {
item.classList.add("red");
item.nextElementSibling.classList.add("red");
}
else{
item.classList.add("green")
item.nextElementSibling.classList.remove("green");
}
})
})
Try this:
inputField.forEach(field => {
field.addEventListener("input", () => {
field.classList.add("green");
});
});
If you want only one field to be green at a time:
inputField.forEach(field => {
field.addEventListener("input", () => {
inputField.forEach(input => {
input.classList.remove("green");
});
field.classList.add("green");
});
});
I'm not sure all your code does what you are expecting, but I have an approach that is approaching your requirement by listening to the keyup event and evaluating if the input has content or not; you should be able to reconfigure this to your use case.
I also moved your loop of the four loops inside the submit button click handler-- otherwise you are adding three identical handlers to the button.
const submitButton = document.getElementById("submit")
const inputField = document.querySelectorAll(".input")
submitButton.addEventListener("click", function(e) {
inputField.forEach(function(item) {
e.preventDefault();
if (item.value == '') {
item.classList.add("red");
item.nextElementSibling.classList.add("red");
} else {
item.classList.add("green")
item.nextElementSibling.classList.remove("green");
}
})
})
inputField.forEach(function (item) {
item.addEventListener('keyup', function(e) {
const theInput = e.target;
if (theInput.value) {
theInput.classList.remove('red');
theInput.classList.add('green');
}
});
});
.red {
border: red 2px solid;
}
.green {
border: green 2px solid;
}
<label for="myfield">My Field:</label>
<input class="input" id="myfield" name="myfield" />
<br/>
<label for="myotherfield">My Other Field:</label>
<input class="input" id="myotherfield" name="myotherfield" />
<button id="submit">Submit</button>
Note another option would be to omit the JavaScript altogether and just go for native validation-- you have less control about when and how the validation styles are applied, but also less JS to write:
const submitButton = document.getElementById("submit")
submitButton.addEventListener("click", function(e) {
e.preventDefault();
});
.input:invalid {
border: red 2px solid;
}
.input:valid {
border: green 2px solid;
}
<label for="myfield">My Field:</label>
<input class="input" id="myfield" name="myfield" required/>
<br/>
<label for="myotherfield">My Other Field:</label>
<input class="input" id="myotherfield" name="myotherfield" required />
<button id="submit">Submit</button>
If you go with the first approach, make sure you are providing adequate feedback for screen readers and assistive technologies to understand the form's state-- if there are no validation or validation-state attributes on the input and you are only indicating validity with a green/red border, screen readers won't be aware of it. Furthermore, those with red/green color blindness might not be able to perceive the difference.
You don't actually need any JavaScript for this. Add the required attribute on the inputs and then style them accordingly with css.
<input type="text" required>
<input type="text" required>
<input type="text" required>
<input type="text" required>
input:valid {
background-color: green;
}
input:invalid:required {
background-color: red;
}
try this for a quick fix:
const submitButton = document.getElementById("submit")
const inputField = document.querySelectorAll(".input")
inputField.forEach(field => {
field.addEventListener("input", () => {
inputField.forEach(input => {
input.classList.remove("green");
input.classList.remove("red");
});
if (field.value !== "") {
field.classList.add("green");
} else {
field.classList.add("red");
}
});
});
I want to show the error message of required if mandatory fields are left blank. I implement it using the following way but every time the function checkinput() is invoked it adds a new span element due to which "required" message is outputted multiple times. I want the span element to be added once and disappears when user fills in the requirement. Here is my code.
const checkinput=(event)=>{
if(event.target.value===""){
event.target.insertAdjacentHTML('afterend','<span class="text-danger">Required</span>')
}
if(event.target.value!==""){
var child=document.querySelector('span');
child.remove();
}
}
document.getElementById("username").addEventListener('blur',checkinput);
document.getElementById("password").addEventListener('blur',checkinput);
document.getElementById("confirmPassword").addEventListener('blur',checkinput);
Reason why new span element is added each time you have a empty input field is because you are calling insertAdjacentHTML each time and inserting a new span element.
What you should do is add span elements with each input field in the html and initially they should be empty.When you want to validate the input fields, if any of the input is empty, select the span element next to that input element and show the error message in that span element using .textContent property. To clear the error message, you just need to set .textContent of the span element to an empty string.
Following code snippets show different ways of validating form inputs.
Form validation on form submit
Following code snippet validates form inputs when form is submitted.
const form = document.querySelector('form');
const usernameError = document.querySelector('#usernameError');
const passwordError = document.querySelector('#passwordError');
form.addEventListener('submit', (event) => {
event.preventDefault();
const usernameValid = validateField(form, 'username', usernameError);
const passwordValid = validateField(form, 'password', passwordError);
if (usernameValid && passwordValid) {
console.log('form submitted');
form.reset();
}
});
function validateField(form, fieldName, errorEl) {
if (form.elements[fieldName].value == '') {
errorEl.textContent = `${fieldName} is required`;
return false;
} else {
errorEl.textContent = '';
return true;
}
}
form div {
margin: 0 0 10px;
display: flex;
flex-direction: column;
max-width: 200px;
}
form label { margin: 0 0 5px; }
span { color: red; }
<form>
<div>
<label>Username</label>
<input type="text" name="username" />
<span id="usernameError"></span>
</div>
<div>
<label>Password</label>
<input type="password" name="password" />
<span id="passwordError"></span>
</div>
<button>Submit</button>
</form>
Form validation on input focus loose
Following code snippet validates form inputs when any of the input looses focus.
const form = document.querySelector('form');
const inputsContainer = document.getElementById('formInputsContainer');
const submitBtn = document.querySelector('button');
form.addEventListener('submit', (event) => {
event.preventDefault();
const usernameValid = validateField(form, 'username');
const passwordValid = validateField(form, 'password');
if (usernameValid && passwordValid) {
console.log('form submitted');
form.reset();
}
});
submitBtn.addEventListener('focus', () => {
form.requestSubmit();
});
inputsContainer.addEventListener('focusout', (event) => {
validateField(form, event.target.name);
});
function validateField(form, fieldName) {
const errorEl = document.getElementById(`${fieldName}Error`);
if (form.elements[fieldName].value == '') {
errorEl.textContent = `${fieldName} is required`;
return false;
} else {
errorEl.textContent = '';
return true;
}
}
form div {
margin: 0 0 10px;
display: flex;
flex-direction: column;
max-width: 200px;
}
form label { margin: 0 0 5px; }
span { color: red; }
<form>
<div id="formInputsContainer">
<div>
<label>Username</label>
<input type="text" name="username" />
<span id="usernameError"></span>
</div>
<div>
<label>Password</label>
<input type="password" name="password" />
<span id="passwordError"></span>
</div>
</div>
<button>Submit</button>
</form>
Form validation as user types in the input field
Following code snippet validates form input as user types in any input field.
const form = document.querySelector('form');
const inputsContainer = document.getElementById('formInputsContainer');
form.addEventListener('submit', (event) => {
event.preventDefault();
const usernameValid = validateField(form, 'username');
const passwordValid = validateField(form, 'password');
if (usernameValid && passwordValid) {
console.log('form submitted');
form.reset();
}
});
inputsContainer.addEventListener('input', (event) => {
validateField(form, event.target.name);
});
function validateField(form, fieldName) {
const errorEl = document.getElementById(`${fieldName}Error`);
if (form.elements[fieldName].value == '') {
errorEl.textContent = `${fieldName} is required`;
return false;
} else {
errorEl.textContent = '';
return true;
}
}
form div {
margin: 0 0 10px;
display: flex;
flex-direction: column;
max-width: 200px;
}
form label { margin: 0 0 5px; }
span { color: red; }
<form>
<div id="formInputsContainer">
<div>
<label>Username</label>
<input type="text" name="username" />
<span id="usernameError"></span>
</div>
<div>
<label>Password</label>
<input type="password" name="password" />
<span id="passwordError"></span>
</div>
</div>
<button>Submit</button>
</form>
You need something like
if(event.target.value==="" && document.querySelector('span') === null){
event.target.insertAdjacentHTML('afterend','<span class="text-danger">Required</span>')
}
if(event.target.value!==""){
var child=document.querySelector('span');
child.remove();
}
You only want to add a span IF the value is an empty string AND the span hsan't been added yet.
You can use this code which create a span which is add to the DOM with the ID which is based on the form element'sname attribute. And that element can be refered to based on the ID which was attach to it before It's been add to the DOM
const checkinput=(event)=>{
if(event.target.value===""){
let spanId = `input-${event.target.name}`
let span = `<span id="${spanId}" class="text-danger">Required</span>`
setTimeout(() =>{
document.getElementById(spanId).remove();
}, 5000);
event.target.insertAdjacentHTML('afterend',span)
}
}
document.getElementById("username").addEventListener('blur',checkinput);
document.getElementById("password").addEventListener('blur',checkinput);
document.getElementById("confirmPassword").addEventListener('blur',checkinput);
<form>
<input type="text" name="username" id="username"/>
<input type="text" name="password" id="password"/>
<input type="text" name="confirmPassword" id="confirmPassword"/>
</form>
May it help
<style>
.errorMsg {
border: 1px solid red;
}
.err {
color: red;
}
</style>
<form>
<input type="text" name="name" id="name">
<input type="password" name="password" id="password">
<button id="submit" type="submit">Submit</button>
</form>
<script>
let nameTag = document.querySelector('#name');
let passwordTag = document.querySelector('#password');
let submitBtn = document.querySelector('#submit');
nameTag.addEventListener('blur', e => validation(e));
passwordTag.addEventListener('blur', e => validation(e));
function validation(e) {
if (e.target.value == '') {
e.target.classList.add('errorMsg')
submitBtn.setAttribute('disabled', true) // Disable submit that user cannot submit
e.target.insertAdjacentHTML('afterend', `<span class="err ${e.target.id}">It is required</span>`)
// In the above line we are inserting an element with class same as id of input that in the remove we remove a particular error message only
} else {
e.target.classList.remove('errorMsg')
submitBtn.removeAttribute('disabled')
document.querySelector(`.err.${e.target.id}`).remove();
//Here code is saying that the element with if 'err' and 'class same as id of input' if both class present then remove it
}
}
</script>
Adding the class = id that a special error message delete
I have a Radio button. I want to implement a validation on "Submit" Anchor tag that displays an error if no selection is made on the radio button and redirects to the URL provided in the href attribute if the radio button selection is made.
Below is the code for radio button -
<div>
<input required="" type="radio" id="group02-0" name="group02" value="Yes" onclick="yesnoCheck();">
<label for="group02-0" >Yes</label>
<input type="radio" id="group02-1" name="group02" value="No" onclick="yesnoCheck();">
<label for="group02-1">No</label>
</div>
<script>
var radio_value = "";
function yesnoCheck() {
radio_value = document.querySelector('input[name="group02"]:checked').value;
}
</script>
In the same HTML file, I have code for the Submit Anchor tag -
<span>Submit</span>
<script>
function submitCheck() {
if (radio_value === "") {
//Display an error. The user should not be taken to the next page
return false;
} else {
//User should be taken to the URL in the href attribute
return true;
}
}
</script>
Irrespective of whether I make a selection on the radio button, the anchor tag always takes me to the next page. Please help!
You don't need two radio buttons. Only one Checkbox.
Use Event.preventDefault() to prevent default browser navigation
Use the input element's checked state to determine the outcome
Finally use document.location to navigate to a EL_submitBtn.getAttribute('href')
PS: Don't use inline JavaScript (in HTML). JS should be in one place and that's your JS file or inside a <script> tag. It's easier to debug and maintain.
Single checkbox
const EL_submitBtn = document.querySelector('#submitBtn');
const EL_acceptCkb = document.querySelector('[name="accept"]');
function submitCheck(ev) {
ev.preventDefault(); // prevent follow link
if (!EL_acceptCkb.checked) { // Unchecked
alert("You will not get a better UX");
} else { // Checked
alert("Yes! Buckle up!")
document.location = EL_submitBtn.getAttribute('href');
}
}
EL_submitBtn.addEventListener('click', submitCheck);
<div>
<h3>Would you like a better UX?</h3>
<label>
<input type="checkbox" name="accept"> Yes I do
</label>
</div>
<a id="submitBtn" href="https://www.google.com">Submit</a>
Two radio buttons
Use document.querySelector('[name="accept"]:checked') to get the checked one, if any.
const EL_submitBtn = document.querySelector('#submitBtn');
function submitCheck(ev) {
ev.preventDefault(); // prevent follow link
const EL_acceptCkd = document.querySelector('[name="accept"]:checked');
if (!EL_acceptCkd) { // None checked
alert("You must select Yes or No.");
} else if (EL_acceptCkd.value === 'no') { // "NO" checked
alert("You will not get a better UX");
} else { // "YES" checked
alert("Yes! Buckle up!")
document.location = EL_submitBtn.getAttribute('href');
}
}
EL_submitBtn.addEventListener('click', submitCheck);
<div>
<h3>Would you like a better UX?</h3>
<label>
<input type="radio" name="accept" value="yes"> Yes
</label>
<label>
<input type="radio" name="accept" value="no"> No
</label>
</div>
<a id="submitBtn" href="https://www.google.com">Submit</a>
use css pointer-events: none; -> https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
If you absolutely want to use button radios (even if it's a bit twisted as an idea) here is the code:
const aHrefGoogle = document.getElementById('aHrefGoogle');
document.querySelectorAll('input[name=group02]').forEach(el=>
{
el.onchange=_=>{ if (el.checked) setLinkOnOff(el.value) }
})
function setLinkOnOff(val)
{
if (val==='yes') { aHrefGoogle.classList.remove('adisableHref') }
else { aHrefGoogle.classList.add('adisableHref') }
}
.adisableHref {
color: grey;
pointer-events: none;
cursor: default;
text-decoration-line: none;
}
make link Google active ?
<label ><input type="radio" name="group02" value="yes">Yes </label>
<label ><input type="radio" name="group02" value="no" checked>No! </label>
<br><br>
<span> Google </span>
for memo here is the initial code with a checkbox :
const yesnoCheck = document.getElementById('yesnoCheck')
, aHrefGoogle = document.getElementById('aHrefGoogle')
;
// init
yesnoCheck.checked = false
aHrefGoogle.classList.add('adisableHref')
yesnoCheck.oninput =_=>
{
if (yesnoCheck.checked) { aHrefGoogle.classList.remove('adisableHref') }
else { aHrefGoogle.classList.add('adisableHref') }
}
#yesnoCheck { display: none; }
#yesnoCheck + label { display: inline-block; background: #cd3c3c; color: white; padding: .17em .2em; cursor: pointer; }
#yesnoCheck:checked + label { background: #378b2c; }
#yesnoCheck + label::before { content: 'NO'; display: inline-block; width:2.6em; text-align: center; }
#yesnoCheck + label::after { content: ''; display: inline-block; width:0; text-align: center; }
#yesnoCheck:checked + label::before { content: ''; width:0; }
#yesnoCheck:checked + label::after { content: 'YES'; width:2.6em; }
.adisableHref {
color: grey;
pointer-events: none;
cursor: default;
text-decoration-line: none;
}
make link Google active ?
<input type="checkbox" id="yesnoCheck"><label for="yesnoCheck">▉</label>
<br><br>
<span> Google </span>
I have a form with ratable options as radio buttons. What I am trying to achieve is the following:
If an option has not been rated, I want the parent div "option-group" to have a red border. Once the option has been rated, I want the red border to disappear. So far, I have not found a solution.
If the error message is visible and all required fields have been filled out, then I want the error message to disappear immediately.
Here comes the fiddle:
http://jsfiddle.net/a05jrdau/9/
Here comes my code:
HTML
<form id="my-form" action="" method="post">
<div id="msg-error"></div>
<input type="text" id="myInput" name="myInput"/>
<div class="option-con">
<div class="option-label">
Option 1
</div>
<div class="option-row">
<input type="radio" name="radioOption1" value="1"/> 1
<input type="radio" name="radioOption1" value="2"/> 2
<input type="radio" name="radioOption1" value="3"/> 3
</div>
</div>
<div class="option-con">
<div class="option-label">
Option 2
</div>
<div class="option-row">
<input type="radio" name="radioOption2" value="1"/> 1
<input type="radio" name="radioOption2" value="2"/> 2
<input type="radio" name="radioOption2" value="3"/> 3
</div>
</div>
<br>
<br>
<input type="submit" value="Test" />
</form>
CSS:
.option-con {
width: 100%;
float: left;
}
.option-label, .option-row {
float: left;
}
.option-row {
margin-left: 10px;
}
.error {
border: 1px solid red;
}
JS:
jQuery(function ($) {
$('#my-form').validate({
debug: true,
rules: {
myInput: {
required: true
},
radioOption1: {
required: true
},
radioOption2: {
required: true
}
},
invalidHandler: function (event, validator) {
if (validator.errorList.length > 0) {
$('#msg-error').empty().html('Please fill in required fields.').show();
} else {
$('#msg-error').hide();
}
},
errorClass: "error"
}
)});
You simply need to conditionally target the parent when the input element is a radio. Use the highlight and unhighlight callback functions to over-ride the default behavior.
highlight: function (element, errorClass, validClass) {
var target;
if ($(element).is(':radio')) {
target = $(element).parent('div');
} else {
target = $(element);
};
target.addClass(errorClass).removeClass(validClass);
},
unhighlight: function (element, errorClass, validClass) {
var target;
if ($(element).is(':radio')) {
target = $(element).parent('div');
} else {
target = $(element);
};
target.addClass(validClass).removeClass(errorClass);
},
Working DEMO: http://jsfiddle.net/a05jrdau/10/
Also note that, to suppress the error messages, you should put a return false inside of the errorPlacement callback function rather than leaving it empty.
errorPlacement: function (error, element) {
return false;
},
You also do not need errorClass: "error" as "error" is the default setting.
EDIT:
Your error message is not clearing on a valid form because you're trying to do that within the invalidHandler, which only fires when the form is invalid AND you click the button. invalidHandler can never clear the error message because it is never called when the form is valid or by any other triggering event.
You would use the showErrors callback instead...
showErrors: function (errorMap, errorList) {
var msgerror = "All fields are required.";
if (this.numberOfInvalids() > 0) {
$('#msg-error').empty().html(msgerror).show();
} else {
$('#msg-error').hide();
};
this.defaultShowErrors();
},
DEMO 2: http://jsfiddle.net/a05jrdau/14/