Задать вопрос
SonyFan23
@SonyFan23

Как исправить ошибки валидации формы?

Подскажите, как решить ошибки? Вообще не понимаю в чем дело.

external.js:75 Uncaught TypeError: Cannot read property 'value' of undefined
    at formValidator (external.js:75)
    at HTMLFormElement.<anonymous> (external.js:145)


  • Вопрос задан
  • 88 просмотров
Подписаться 1 Простой 1 комментарий
Помогут разобраться в теме Все курсы
  • Нетология
    Веб-разработчик с нуля: профессия с выбором специализации
    14 месяцев
    Далее
  • Академия Эдюсон
    Fullstack-разработчик на JavaScript + ИИ
    11 месяцев
    Далее
  • ProductStar × РБК
    Профессия: Инженер по тестированию + ИИ
    6 месяцев
    Далее
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
if (inputs[el].value == "") el++;

if (inputs[el].value.match(/[А-я]/)) {

Давайте представим, что пустое значение имеет последний элемент. Делаете свой ++, а затем пытаетесь элемент обработать - следующий, которого НЕТ. А раз его нет, значит он undefined, а у undefined никакого value быть не может, как и любых других свойств. Если не хотите обрабатывать пустой элемент - выполняйте прерывание текущей итерации цикла вместо вот этих вот стрёмных манипуляций со счётчиком (кстати, а какого чёрта el? - весьма странное имя для счётчика цикла, он же представляет не сам элемент, а его индекс в коллекции).

Это если говорить про заявленную в вопросе проблему в виде "cannot read property". Но кроме неё присутствует и ряд других косяков (сильно к коду не приглядывался, так что возможно есть ещё, помимо нижеперечисленного), не столь очевидных, но также способных стать причиной неправильной работы формы:

  • Отказ от обработки незаполненных элементов приведёт к тому, что иногда они будут выделяться как невалидные, а иногда нет - в зависимости от их состояния до ввода пустой строки. Например, вводим в первое поле 1 - элемент выделяется как некорректно заполненный; удаляем содержимое - выделение сохраняется; вводим й - выделение снимается; удаляем - элемент по-прежнему выглядит корректно заполненным. Определитесь, надо ли выделять пустые элементы как невалидные.
  • Регулярное выражение из процитированного выше куска кода - /[А-я]/. Давайте-ка взглянем повнимательнее на края диапазона:

    'А'.charCodeAt() // 1040
    'я'.charCodeAt() // 1103

    Ничего странного не видите? А между тем, длина диапазона - 64. Что, всё ещё ничего странного? Ну а букв в русском алфавите сколько? 33. Значит, в обоих регистрах должно быть 66. Кого потеряли? Да конечно же ё:

    'Ё'.charCodeAt() // 1025
    'ё'.charCodeAt() // 1105

    Как будет правильно: /[а-яё]/i. Т.е., перечисляем буквы - все, не забывая отдельно указать выбивающуюся из общего ряда ё - только в одном из регистров, и добавляем флаг регистронезависимого поиска.
  • Разблокировка кнопки отправки формы:

    document.querySelector(".form").addEventListener("change", () => {
    
      
        if (formValidator() == true) {
    
            btnSubmit.classList.add("btn-active");
            btnSubmit.removeAttribute("disabled");
        }
    });

    Вы действительно считаете, что если форма заполнена корректно, то её содержимое уже нельзя отредактировать так, чтобы оно перестало быть валидными? Надо disabled не только убирать, но и добавлять - в зависимости от того, что вернёт formValidator.

    Не так чтобы прям жёсткие косяки, но упомянуть стоит: управлять наличием атрибута disabled будет короче через свойство; вместо change лучше обрабатывать input; цеплять дополнительный класс нет необходимости, пусть кнопка по умолчанию стилизуется как активная, а "неактивные" стили унесите в .btn-submit:disabled.


А вообще, есть мнение, что стоит придать этой валидации чуть более пристойный вид. Сделаем объект, содержащий функции для проверки значений, ключами будут имена полей:

const validators = {
  date: val => /^\d{4}$/.test(val),
  course: val => /^[1-6]$/.test(val),
  __default: val => /[а-яё]/i.test(val),
};

При переборе элементов достаём функцию, передаём ей значение элемента. Ну и всё - больше не надо никаких магических чисел, цепочки из условных операторов, дублирования кода добавления класса:

const formValidator = el =>
  inputs.length === Array.prototype.reduce.call(
    inputs,
    (acc, n) => {
      const isValid = (validators[n.name] || validators.__default)(n.value);
      (!el || el === n) && n.classList.toggle('invalid-input', !isValid);
      return acc + isValid;
    },
    0
  );

Обратите внимание на то, что у formValidator появился параметр - элемент, который был подвергнут редактированию. Если указан, то только у него будет переключаться класс. Т.е., теперь можно пустое значение рассматривать как некорректное, но пока пользователь элемент не трогал, не подсвечивать его (подозреваю, что именно этого поведения вы стремились добиться в попытке не обрабатывать пустые элементы). Откуда брать элемент, который пользователь редактировал? - да из объекта события:

document.querySelector('.form').addEventListener('input', e => {
  btnSubmit.disabled = !formValidator(e.target);
});
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы