Built-in HTML5 form validation for individual fieldset? - javascript

Is it possible to use browsers' built-in HTML5 form validation on an individual fieldset?
I'm building a multi step form but would like to use the browser's built-in validation tool to detect and display validation messages for inputs on the currently displayed fieldset, rather than on the entire form (Chrome gives an error here because the input in the hidden fieldset is not focusable, besides I don't want it to validate the second input when the first button is clicked)
I know you can do custom JS validation and error display, but I want to know if it's possible to use the browser validation on an individual fieldset.
const form = document.getElementById('form')
const first = document.getElementById('first')
const second = document.getElementById('second')
form.addEventListener('submit', (e) => {
e.preventDefault();
first.style.display = 'none';
second.style.display = 'block';
})
<form id="form">
<fieldset id="first">
<legend>first</legend>
<input name="firstInput" required>
<button>next step</button>
</fieldset>
<fieldset id="second" style="display: none;">
<legend>second</legend>
<input required name="secondInput">
<button>Submit</button>
</fieldset>
</form>

I've managed to get what I need like this.
Remove required from all inputs that are not displayed when the page loads
When the function to show the next fieldset runs, it sets all the inputs on the newly displayed fieldset (except checkboxes) as required
If you want to move back to the previous fieldset, the function removes required from the inputs in the fieldset you've just hidden, otherwise you wouldn't be able to move forward again (because the <input required> in the hidden fieldset cannot be focused, the htmll5 validation breaks)
At the last step, the form submits as expected
I'm including my code in case it can help someone.
form = document.getElementById('Form');
fieldsets = document.querySelectorAll('fieldset');
back = document.getElementById('back');
nextORsubmit = document.getElementById('nextORsubmit');
let i = 0;
form.addEventListener('submit', (e) => {
if (i < fieldsets.length - 1) {
e.preventDefault();
console.log('Validate, but don\'t send form');
fieldsets[i].style.display = 'none';
fieldsets[i+1].style.display = 'block';
back.style.display = 'inline';
i++;
// set required on current fieldset inputs, except if they're checkboxes
fieldsets[i].querySelectorAll('input:not([type="checkbox"])').forEach (el => {
el.required = true;
})
}
});
back.addEventListener('click', () => {
console.log('going back a step');
fieldsets[i].style.display = 'none';
fieldsets[i-1].style.display = 'block';
i--;
// remove required on inputs from the next fieldset that we've just hid
fieldsets[i+1].querySelectorAll('input:not([type="checkbox"])').forEach (el => {
el.required = false;
})
// remove back button when you go back to the first step
if (i == 0) {
back.style.display = 'none';
}
})
#back,
fieldset:not(:first-of-type) {
display: none;
}
<form id="Form">
<fieldset>
<legend>first</legend>
<input name="firstInput" required>
</fieldset>
<fieldset>
<legend>second</legend>
<input name="secondInput">
</fieldset>
<fieldset>
<legend>third</legend>
<input name="thirdInput">
</fieldset>
<button id="back" type="button">Back</button><br>
<button id="nextORsubmit">Next</button>
</form>

Related

How to enable disabled the submit button using JavaScript or jQuery?

I have a form Data in the HTML like the below,
Blade file:
<form method="post" action="someURL" id="register">
<input type="text" name="name" id="name" />
<div class="error">{{ $errors->first('name') }}</div>
<input type="email" name="email" id="email"/>
<div class="error">{{ $errors->first('email') }}</div>
<textarea name="body" id="message"> Enter your message here</textarea>
<div class="error">{{ $errors->first('message') }}</div>
<input type="submit" id="btnSubmit" disabled />
</form>
<script>
const button = document.querySelector("#btnSubmit");
const buttonExpirationDataKey = 'button-disabled-expiration';
let startButtonStateCheck = () => {
button.dataset.interval = setInterval(updateButtonState, 1000);
}
let updateButtonState = () => {
let expirationDate = new Date(button.dataset.enabledAt);
if (expirationDate < new Date()) {
button.disabled = false;
clearInterval(button.dataset.interval);
} else {
button.disabled = true;
}
}
let buttonDisableExpiration = localStorage.getItem(buttonExpirationDataKey);
if (!buttonDisableExpiration) {
// no button state in localStorage, enable button
button.disabled = false;
} else {
// button state held in localStorage, check every 1s for expiration to enable the button again
button.dataset.enabledAt = buttonDisableExpiration;
updateButtonState();
startButtonStateCheck();
}
button.addEventListener("click", () => {
var form = document.getElementById("register");
var fields = ["name", "email", "body"];
var i, l = fields.length;
var fieldname;
for (i = 0; i < l; i++) {
fieldname = fields[i];
if (form[fieldname].value === "") {
button.disabled = false;
}
else{
button.disabled = true;
let now = new Date();
let expirationTime = 1000 * 10;
let expirationDate = new Date(now.getTime() + expirationTime);
localStorage.setItem(buttonExpirationDataKey, expirationDate);
button.dataset.enabledAt = expirationDate;
startButtonStateCheck();
}
}
});
</script>
In controller::
$data = request()->validate([
'name' => 'required',
'email' => 'required|email',
'body' => 'required',
]);
I have validated the fields in the controller.
The Submit button on click should check whether all the Input Values were given, If either one of the values is missing, the Submit button should be Enabled, even on click. I have given the validation in the controller
In my code, the submit button is disabled every time, when it is clicked even without the input values. But, it shows the error as This field is required near the input fields, when we click the submit button.
I need the submit button to be Disabled on click, when all the input values were given and then storing the button Enabled and Disabled in the Local storage.
When a user submits the form, without entering the form input, the button should be Enabled.
But, the submit button is not working as expected. It gets disabled, even without the form inputs
How could I do this? Could anyone please help?
Here first you will have to prevent the default action of the form so you need to use preventDefault() on event and than after all validations check you can manually submit or enable the button. But the main thing is that you need to disable the default behaviour to add your own custom checks.
Here is a fiddle to show :
https://jsfiddle.net/g6wfkj74/7/
Hope this helped

How to remove oninvalid for every input except one using javascript?

I created a form with some input fields and the user needs to fill at least one field and if the user doesn't select any then the error will be shown. I achieve that goal but I need to show my custom require message as invalid. Because of the oninvalid on every input, My code is not working properly but I want this message to show so how can I remove oninvalid from the rest of the input fields rather than the filled one?
<form>
<input name="youtube" oninvalid="this.setCustomValidity('Please fill out at least one social media field')" required/>
<input name="vimeo" oninvalid="this.setCustomValidity('Please fill out at least one social media field')" required/>
<input name="pinterest" oninvalid="this.setCustomValidity('Please fill out at least one social media field')" required/>
<input type="submit" name="submit" value="Submit" id="ls-submit">
</form>
document.addEventListener('DOMContentLoaded', function () {
const inputs = Array.from(document.querySelectorAll('input[name=youtube], input[name=vimeo], input[name=pinterest]'));
const inputListener = e => inputs.filter(i => i !== e.target).forEach(i => i.required = !e.target.value.length, i => i.oninvalid = !e.target.value.length);
inputs.forEach(i => i.addEventListener('input', inputListener));
});
I really don't have an idea what to do. We can also use alert as an error message and I tried that too but didn't get any success.
You could remove oninvalid and required from all inputs and check it instead with javascript:
var inputs = document.querySelectorAll('input');
document.querySelector('button').addEventListener('click', function() {
var valid = false;
for(i = 0; i < inputs.length; i++) {
if ( inputs[i].value != "" ) {
valid = true;
break;
}
}
if (valid) {
document.querySelector("form").submit();
}
else {
alert('Please fill out at least one social media field');
}
});
Working example (with 'alert' instead of 'setCustomValidity'):
var inputs = document.querySelectorAll('input');
document.querySelector('button').addEventListener('click', function() {
for(i = 0; i < inputs.length; i++) {
var valid = false;
if ( inputs[i].value != "" ) {
valid = true;
break;
}
}
if (valid) {
document.querySelector("form").submit();
}
else {
alert('Please fill out at least one social media field');
}
});
<form action="https://stackoverflow.com" method="GET">
<input name="youtube" value="">
<input name="vimeo" value="">
<input name="pinterest" value="">
<button type="button">submit</button>
</form>

Listen for blank inputs and add a "disabled" attribute to a button until an input is noticed

I have a user input field that, if blank, I would like the submit button to be disabled until a key press in the input box is noticed. But, if they blank out the input box, then the button is disabled again.
So, I'd like to add the "disabled" attribute to this input button:
<input type="submit" id="mapOneSubmit" value="Submit" [add attribute "disabled" here]>
The input is from this HTML here:
<input type="text" id="mapOneUserInput" onkeypress="return isNumberKey(event)" oninput="validate(this)">
Note: I have onkeypress and oninput validation to prevent non-number inputs and allow only 2 decimal places.
I assume my JS would look like this to add the disabled attribute:
document.getElementById("mapOneSubmit").setAttribute("disabled");
My problem is, I can't find what event listener listens for "blank" inputs? Can you help me with that?
Thanks kindly!
Check this one as well.
function checkvalid(el)
{
//e.g i am preventing user here to input only upto 5 characters
//you can put your own validation logic here
if(el.value.length===0 || el.value.length>5)
document.getElementById("mapOneSubmit").setAttribute("disabled","disabled");
else
document.getElementById("mapOneSubmit").removeAttribute('disabled');
}
<input type='text' id ='inp' onkeyup='checkvalid(this)'>
<button id='mapOneSubmit' disabled>
Submit
</button>
Yet using the input event:
<input type="text" id="mapOneUserInput" onkeypress="return isNumberKey(event)" oninput="validate(this);updateSubmit(this.value)">
Then in js
function updateSubmit(val) {
if (val.trim() == '') {
document.getElementById('mapOneSubmit').disabled = true;
}
else {
document.getElementById('mapOneSubmit').disabled = false;
}
}
You can find the below code to find the blank inputs
function isNumberKey(event) {
console.log(event.which)
}
var value;
function validate(target) {
console.log(target);
}
<form>
<input type="text" id="mapOneUserInput" onkeypress="return isNumberKey(event)" oninput="validate(this)">
<input type="submit" id="mapOneSubmit" value="Submit" [add attribute "disabled" here]>
</form>
You can you set the enable/disable inside validate function.
function validate(elem) {
//validation here
//code to disable/enable the button
document.getElementById("mapOneSubmit").disabled = elem.value.length === 0;
}
Set the button disable on load by adding disabled property
<input type="submit" id="mapOneSubmit" value="Submit" disabled>
On your validate function just check if value of input field is blank then enable/disable the button
function validate(input){
input.disabled = input.value === "" ;
}
My problem is, I can't find what event listener listens for "blank" inputs?
You can disable the submit button at render, after that you can use the input event to determine whether the input value is empty or not. From there, you can set state of the submit button.
document.addEventListener('DOMContentLoaded', () => {
const textInput = document.getElementById('mapOneUserInput');
textInput.addEventListener('input', handleTextInput, false);
textInput.addEventListener('keydown', validateInput, false);
});
function handleTextInput(event) {
const { value } = event.target;
if (value) {
enableSubmitButton(true);
} else {
enableSubmitButton(false);
}
}
// Refer to https://stackoverflow.com/a/46203928/7583537
function validateInput(event) {
const regex = /^\d*(\.\d{0,2})?$/g;
const prevVal = event.target.value;
const input = this;
setTimeout(function() {
var nextVal = event.target.value;
if (!regex.test(nextVal)) {
input.value = prevVal;
}
}, 0);
}
function enableSubmitButton(isEnable) {
const button = document.getElementById('mapOneSubmit');
if (isEnable) {
button.removeAttribute('disabled');
} else {
button.setAttribute('disabled', '');
}
}
<input type="number" value="" id="mapOneUserInput">
<!-- Note that the input blank at render so we disable submit button -->
<input type="submit" id="mapOneSubmit" value="Submit" disabled>

How to dynamically keep track of user inputs in JavaScript?

Does anyone have any idea to dynamically keep track of user inputs in a form? I learned how to disable a button and if users want to enable it, they would just have to fill in the input fields. While this works, if a user decides to backspace and go back to a clear field, the button is still enabled. I wanted to get some insight or ideas to keep track of user inputs dynamically.
I'm a bit new to JS so I just wanted some ideas. Is it possible to use for loops/forEach methods to iterate through the input fields? Or what approach do you recommend on taking?
HTML:
<form class="container">
<input type="text" class="input" />
<input type="email" class="input" id="input" />
<button type="submit" id="submitButton" href="index.html" disabled>
Submit
</button>
</form>
JavaScript:
document.getElementById("input").addEventListener("keyup", function() {
var inputs = document.querySelectorAll("input");
if (inputs != "") {
document.getElementById("submitButton").removeAttribute("disabled");
} else if ((inputs = "")) {
document.getElementById("submitButton").setAttribute("disabled", null);
}
});
Here is the solution of your problem.
document.addEventListener("keyup", function() {
var inputs = document.querySelectorAll("input");
var emptyFillExists = false;
for (let index = 0; index < inputs.length; index++) {
if (inputs[index].value.length === 0) {
emptyFillExists = true;
break;
}
}
if (!emptyFillExists) {
document.getElementById("submitButton").removeAttribute("disabled");
} else {
document.getElementById("submitButton").setAttribute("disabled", null);
}
});
<form class="container">
<input type="text" class="input" />
<input type="email" class="input" />
<button type="submit" id="submitButton" href="index.html" disabled>
Submit
</button>
</form>
There are a few things wrong with your codes:
You assume inputs as strings. It isn't. It's an array.
You track keyup event for only 1 input. You should track keyup event for all inputs instead.
Here's what I'd suggest you do:
Add event listener keyup for the form.
Interate through each input and check.
function areInputsValid() {
// Iterate through every input and check its value
var inputs = document.querySelectorAll('input');
for (var i = 0; i < inputs.length; i++)
if (inputs[i].value == '')
return false;
return true;
}
// Get the form element
var form = document.getElementsByTagName('form')[0];
// Add event listener
form.addEventListener('keyup', function() {
// Are the inputs valid?
if (areInputsValid())
document.getElementById("submitButton").removeAttribute("disabled");
else
document.getElementById("submitButton").setAttribute("disabled", null);
})
EDIT: as charlietfl pointed out, there are bugs in my previous answer.

Disable button after adding task to task list

I would like to add some items to task list and disable button each time. When page loads it works fine.
I'd like to also disable button after adding each task.
If you add a new task and press submit button it works fine. But if the user choose pressing 'Enter' button instead of submit it becomes enabled.
What should it be done to disable submit button if the user prefers 'Enter' button instead of submit button ?
<!DOCTYPE html>
<html>
<head>
<script>
document.addEventListener('DOMContentLoaded', () => {
// By default, submit button is disabled
document.querySelector('#submit').disabled = true;
// Enable button only if there is text in the input field
document.querySelector('#task').onkeyup = () => {
document.querySelector('#submit').disabled = false;
};
document.querySelector('#new-task').onsubmit = () => {
// Create new item for list
const li = document.createElement('li');
li.innerHTML = document.querySelector('#task').value;
// Add new item to task list
document.querySelector('#tasks').append(li);
// Clear input field and disable button again
document.querySelector('#task').value = '';
document.querySelector('#submit').disabled = true;
// Stop form from submitting
return false;
};
});
</script>
<title>Tasks</title>
</head>
Body part of the html.
<body>
<h1>Tasks</h1>
<ul id="tasks">
</ul>
<form id="new-task">
<input id="task" autocomplete="off" autofocus placeholder="New Task" type="text">
<input id="submit" type="submit">
</form>
</body>
</html>
When you click the enter button, your onkeyup event handler changes the submit button disabled state to false, and the enter works.
Instead, listen to the input event of the #task box, and enable/disable the submit button according to the changes in the content. This will also handle the case in which submit is enabled after the text was deleted.
// Enable button only if there is text in the input field
document.querySelector('#task').addEventListener('input', (e) => {
document.querySelector('#submit').disabled = e.target.value === '';
});
Example:
// By default, submit button is disabled
document.querySelector('#submit').disabled = true;
// Enable button only if there is text in the input field
document.querySelector('#task').addEventListener('input', (e) => {
document.querySelector('#submit').disabled = e.target.value === '';
});
document.querySelector('#new-task').onsubmit = () => {
// Create new item for list
const li = document.createElement('li');
li.innerHTML = document.querySelector('#task').value;
// Add new item to task list
document.querySelector('#tasks').append(li);
// Clear input field and disable button again
document.querySelector('#task').value = '';
document.querySelector('#submit').disabled = true;
// Stop form from submitting
return false;
};
#submit:disabled {
opacity: 0.5;
}
<h1>Tasks</h1>
<ul id="tasks">
</ul>
<form id="new-task">
<input id="task" autocomplete="off" autofocus placeholder="New Task" type="text">
<input id="submit" type="submit">
</form>
When you press enter key the event listner keyup is firing. You have to put the enable of button here in conditions
document.querySelector('#task').onkeyup = (e) => {
if(e.which === 13){
return; // When user enter key press
}
document.querySelector('#submit').disabled = false;
};
I was watching Harvard CS50 Web Programming Course and I'd like to share another solution. This is not a part of homework, assignment etc. so I feel free to share solution.
Basically we enable button if there is text in the input field.
// Enable button only if there is text in the input field
document.querySelector('#task').onkeyup = () => {
if (document.querySelector('#task').value.length > 0)
document.querySelector('#submit').disabled = false;
else
document.querySelector('#submit').disabled = true;
};
// By default, submit button is disabled
document.querySelector('#submit').disabled = true;
// Enable button only if there is text in the input field
document.querySelector('#task').onkeyup = () => {
if (document.querySelector('#task').value.length > 0)
document.querySelector('#submit').disabled = false;
else
document.querySelector('#submit').disabled = true;
};
document.querySelector('#new-task').onsubmit = () => {
// Create new item for list
const li = document.createElement('li');
li.innerHTML = document.querySelector('#task').value;
// Add new item to task list
document.querySelector('#tasks').append(li);
// Clear input field and disable button again
document.querySelector('#task').value = '';
document.querySelector('#submit').disabled = true;
// Stop form from submitting
return false;
};
#submit:disabled {
opacity: 0.5;
}
<h1>Tasks</h1>
<ul id="tasks">
</ul>
<form id="new-task">
<input id="task" autocomplete="off" autofocus placeholder="New Task" type="text">
<input id="submit" type="submit">
</form>

Categories

Resources