Мы с вами изучили базовые методы для работы с DOM. в заключение хотелось бы на практике применить то, чему мы научились.
Поэтому в этом уроке мы с вами напишем валидацию формы на javascript. То есть мы будем проверять данные и условия во всех полях, и если в них есть ошибки, то выводить их на экран.
Давайте добавим нашу форму. Главное, что нам нужно сделать, это добавить классы на все елементы формы, с которыми нам прийдется взаимодействовать.
<form class='formWithValidation'>
<div>
<div>
<label>From:</label>
</div>
<div>
<input type='text' class='from' />
</div>
</div>
<div>
<div>
<label>Password:</label>
</div>
<div>
<input type='password' class='password' />
</div>
</div>
<div>
<div>
<label>Password confirmation:</label>
</div>
<div>
<input type='password' class='passwordConfirmation' />
</div>
</div>
<div>
<div>
<label>Where</label>
</div>
<div>
<select class='where'>
<option></option>
<option value='developers'>Developers</option>
<option value='managers'>Managers</option>
<option value='devops'>DevOps</option>
</select>
</div>
</div>
<div>
<div>
<label>Message:</label>
</div>
<div>
<textarea class='message'></textarea>
</div>
</div>
<input type='submit' class='validateBtn' value='Validate'/>
</form>
Теперь давайте писать валидацию формы. Сначала мы бы хотели найти все элементы, с которыми мы будем работать, но мы хотим их не просто искать в DOMе, а только внутри класса formWithValidation, так как это обезопашивает нас от того, что такие классы будут использоваться где-то еще.
Давайте найдем с вами кнопку Validate
var validateBtn = document.querySelector('.formWithValidation .validateBtn')
Как вы видите, каждый раз, когда мы захотим находить елемент внутри formWithValidation, нам прийдется указывать его в querySelector. Старайтесь всегда избегать лишних и ненужных повторений кода.
В данном случае мы можем вынести поиск formWithValidation отдельно и все остальные елементы искать относительно него
var form = document.querySelector('.formWithValidation')
var validateBtn = form.querySelector('.validateBtn')
Так намного читабельнее. Теперь давайте начнем писать код, а остальные елементы будем добавлять по мере надобности.
Сейчас нам нужно повесить евент submit на нашу форму. Тогда при нажатии enter на любом поле либо на клик Validate, форма отправится. Мы с вами это уже делали
form.addEventListener('submit', function () {
console.log('clicked on validate')
})
Если мы посмотрим в браузер, то происходит следующее. Мы видим наш console.log, но только на доли секунды. Это происходит потому, что html по умолчанию отправляет форму и перезагружает при этом страницу.
Нам в javascript, это совсем не нужно. Для этого существует метод preventDefault. То есть он запрещает поведение по умолчанию. В функции, которая срабатывает у нас при submit, первым параметром нам приходит event. На нем то нам и нужно вызвать eventPreventDefault.
form.addEventListener('submit', function (event) {
event.preventDefault()
console.log('clicked on validate')
})
Если мы посмотрим сейчас, то у нас срабатывает submit и выводится console.log.
Теперь для начала давайте прочитаем значения всех полей при валидации формы.
Начнем в from
var form = document.querySelector('.formWithValidation')
var validateBtn = form.querySelector('.validateBtn')
var from = form.querySelector('.from')
form.addEventListener('submit', function (event) {
event.preventDefault()
console.log('clicked on validate')
console.log('from: ', from.value)
})
Если мы посмотрим в браузер, у нас вывелось текущее значение поля from. То же самое сделаем с всеми полями.
var form = document.querySelector('.formWithValidation')
var validateBtn = form.querySelector('.validateBtn')
var from = form.querySelector('.from')
var password = form.querySelector('.password')
var passwordConfirmation = form.querySelector('.passwordConfirmation')
var passwordConfirmation = form.querySelector('.passwordConfirmation')
var where = form.querySelector('.where')
var message = form.querySelector('.message')
form.addEventListener('submit', function (event) {
event.preventDefault()
console.log('clicked on validate')
console.log('from: ', from.value)
console.log('password: ', password.value)
console.log('passwordConfirmation: ', passwordConfirmation.value)
console.log('where: ', where.value)
console.log('message: ', message.value)
})
Теперь мы хотим проверить, что все поля у нас заполнены. Мы бы могли написать кучу if условий в стиле
if (!from.value) {
// show from error
}
if (!password.value) {
// show passoword error
}
Но это огромное количество кода, которое мы можем упростить. Мы можем пройтить по всем елементам, которые у нас есть и проверить пустой или нет. Для того, чтобы это сделать давайте добавим на каждый елемент формы одинаковый класс. например field.
Например
<input type='text' class='from field' />
Теперь мы можем найти все елементы сразу и пройти по ним циклом, чтобы проверить заполнено ли поле.
var fields = form.querySelectorAll('.field')
form.addEventListener('submit', function (event) {
event.preventDefault()
for (var i = 0; i < fields.length; i++) {
if (!fields[i].value) {
console.log('field is blank', fields[i])
}
}
})
Если мы посмотрим в браузер, то нам в консоль вывелись ошибки. И теперь хотелось бы вывести эти ошибки на форму. Мы можем сгенерировать новый елемент и добавим к каждому полю, которое не заполнено.
Давайте создадим новые елемент. Добавим еще красный цвет и текст Cannot be blank. Теперь, чтобы вставить его перед нашими полями используем insertBefore. А так как нам нужно указать парента, то используем .parentElement.
for (var i = 0; i < fields.length; i++) {
if (!fields[i].value) {
console.log('field is blank', fields[i])
var error = document.createElement('div')
error.className='error'
error.style.color = 'red'
error.innerHTML = 'Cannot be blank'
form[i].parentElement.insertBefore(error, fields[i])
}
}
Если мы посмотрим в браузер, то у нас вывелась валидация всех полей.
Но если мы нажмем еще раз validate, то все наши сообщения сдублируются. Самый простой способ этого избежать, это удалять все ошибки с страницы при валидации.
form.addEventListener('submit', function (event) {
event.preventDefault()
var errors = form.querySelectorAll('.error')
for (var i = 0; i < errors.length; i++) {
errors[i].remove()
}
for (var i = 0; i < fields.length; i++) {
if (!fields[i].value) {
console.log('field is blank', fields[i])
var error = document.createElement('div')
error.className = 'error'
error.style.color = 'red'
error.innerHTML = 'Cannot be blank'
form[i].parentElement.insertBefore(error, fields[i])
}
}
})
Если мы посмотрим в браузер, то ошибки перестали дублироваться.
Теперь давайте добавим проверку на ошибку, когда у нас не совпадают пароли. Просто напишем условие, что пароли не совпадают, а внутри создадим новый error и добавим перед паролем.
form.addEventListener('submit', function (event) {
event.preventDefault()
var errors = form.querySelectorAll('.error')
for (var i = 0; i < errors.length; i++) {
errors[i].remove()
}
for (var i = 0; i < fields.length; i++) {
if (!fields[i].value) {
console.log('field is blank', fields[i])
var error = document.createElement('div')
error.className = 'error'
error.style.color = 'red'
error.innerHTML = 'Cannot be blank'
form[i].parentElement.insertBefore(error, fields[i])
}
}
if (password.value !== passwordConfirmation.value) {
console.log('not equals')
var error = document.createElement('div')
error.className = 'error'
error.style.color = 'red'
error.innerHTML = 'Passwords doesnt match'
password.parentElement.insertBefore(error, password)
}
})
Если мы посмотрим в браузер, то когда пароли разные, у нас выводится ошибка.
Теперь хотелось бы сделать этот код понятнее, так как у сейчас его сложно читать и поддерживать. Давайте для начала создадим функцию, которая будет принимать на вход строку и возвращать DOM елемент.
var generateError = function (text) {
var error = document.createElement('div')
error.className = 'error'
error.style.color = 'red'
error.innerHTML = text
return error
}
И теперь мы можем убрать повторяющийся код
form.addEventListener('submit', function (event) {
event.preventDefault()
var errors = form.querySelectorAll('.error')
for (var i = 0; i < errors.length; i++) {
errors[i].remove()
}
for (var i = 0; i < fields.length; i++) {
if (!fields[i].value) {
console.log('field is blank', fields[i])
var error = generateError('Cant be blank')
form[i].parentElement.insertBefore(error, fields[i])
}
}
if (password.value !== passwordConfirmation.value) {
console.log('not equals')
var error = generateError('Password doesnt match')
password.parentElement.insertBefore(error, password)
}
})
Теперь давайте вынесем в отдельную функцию очистку ошибок.
var removeValidation = function () {
var errors = form.querySelectorAll('.error')
for (var i = 0; i < errors.length; i++) {
errors[i].remove()
}
}
И вызовем ее
form.addEventListener('submit', function (event) {
event.preventDefault()
removeValidation()
for (var i = 0; i < fields.length; i++) {
if (!fields[i].value) {
console.log('field is blank', fields[i])
var error = generateError('Cant be blank')
form[i].parentElement.insertBefore(error, fields[i])
}
}
if (password.value !== passwordConfirmation.value) {
console.log('not equals')
var error = generateError('Password doesnt match')
password.parentElement.insertBefore(error, password)
}
})
И вынесем проверку полей на пустоту
var checkFieldsPresence = function () {
for (var i = 0; i < fields.length; i++) {
if (!fields[i].value) {
console.log('field is blank', fields[i])
var error = generateError('Cant be blank')
form[i].parentElement.insertBefore(error, fields[i])
}
}
}
И вызовем ее
form.addEventListener('submit', function (event) {
event.preventDefault()
removeValidation()
checkFieldsPresence()
if (password.value !== passwordConfirmation.value) {
console.log('not equals')
var error = generateError('Password doesnt match')
password.parentElement.insertBefore(error, password)
}
})
И вынесем валидацию пароля
var checkPasswordMatch = function () {
if (password.value !== passwordConfirmation.value) {
console.log('not equals')
var error = generateError('Password doesnt match')
console.log(error)
password.parentElement.insertBefore(error, password)
}
}
Вот теперь наш код намного проще читать
form.addEventListener('submit', function (event) {
event.preventDefault()
removeValidation()
checkFieldsPresence()
checkPasswordMatch()
})
Итак в этом уроке мы с вами научились валидировать формы на javascript.
Если у вас что-то не получается, либо возникли вопросы и комментарии, пишите их прямо под этим видео и я обязательно на них отвечу.