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>