Проверка формы, когда требуется либо «выбрать» ИЛИ «ввод» - PullRequest
0 голосов
/ 26 августа 2018

У меня есть страница, содержащая несколько форм, все разные, и когда одна из них отправляется, я использую функцию ниже, чтобы собрать все входные данные из этой формы с классом «required» и проверить наличие пустых значений:

function validateForm(form) {
  var inputs = form.getElementsByTagName('input');
  var selects = form.getElementsByTagName('select');
  var errors = 0;

  for (var i = 0; i < inputs.length; i++) {
    if(inputs[i].classList.contains('required')) {    
      if(inputs[i].value === "") {
        inputs[i].classList.add("warning");
        errors++;
      } else {
        inputs[i].classList.remove("warning");
      }
    }
  }
  if(errors) {
    return false;
  } else {
    return true;
  }
}

Если он находит пустое значение, он добавляет класс «warning», который просто придает вводу красную рамку, а затем возвращает false, чтобы форма не была отправлена.

Вот где я столкнулся с проблемой: некоторые формы содержат

Допустим, форма для добавления нового продукта.Выбор динамически заполняется существующими «категориями» продукта, а текстовый ввод предназначен, если пользователь хочет создать новую категорию.Вот упрощенная версия формы:

    <form method = "post" onsubmit = "return validateForm(this)">
      <div class = "form-group">
        <label>Product Name</label>
        <input class = "form-control required" type = "text" name = "product" />
      </div>
      <div class = "form-group">
        <select class = "form-control required" id = "category" name = "category[]">
          <option value = "">Select Existing Category</option>
          <option value = "Shirts">Shirts</option>
          <option value = "Shoes">Shoes</option>
          <option value = "Pants">Pants</option>
        </select>
      </div>
      <div class = "form-group">
        <label>Create New Category</label>
        <input class = "form-control required" type = "text" name = "category[]" />
      </div>
      <div class = "form-group">
        <input class = "btn btn-primary" type = "submit" value = "Submit" />
      </div>
    </form>

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

  if((selects[i].value === "" && inputs[i].value === "") || (selects[i].value !== "" && inputs[i].value !== "")) {
    // add the warning class to both
   }

Я чувствую, что ответ лежит где-то в использовании атрибута name, т. е. сравните selects.name и input.name, но как мне обойти отличающийся индекс в цикле?И также, это должно только сделать это сравнение, когда выбор встречается так или иначе.Это не обязательно существует, в зависимости от формы.

По сути, мне нужно изменить мою функцию, чтобы сделать это:

I.Соберите все входные данные и выберите (если есть - некоторые формы не будут) из отправленной формы

II.Убедитесь, что ни один из входов с классом «required» не является пустым (если нет соответствующего выбора, в этом случае см. III ниже)

III.Если есть выбор, найдите текстовый ввод с тем же «именем» (не обязательно иметь такое же имя, но я предполагаю, что это правильный способ сделать это).Один из них, но не оба, должен иметь значение.Если оба поля пустые или оба имеют значение, они должны получить класс «warning»;

Любая помощь, которую кто-либо может предложить, будет принята с благодарностью!

1 Ответ

0 голосов
/ 26 августа 2018

Вот функция, которая делает именно то, что вы хотите, и может обрабатывать любую форму, которую вы хотите, при условии, что они имеют одинаковую структуру HTML.

Примечания:

  • Я рекомендую избегать встроенных слушателей событий как можно больше, в фрагмент ниже я использовал addEventListener метод для прикрепления submit событие для всех форм в документе, вы можете изменить это просто некоторые конкретные формы, если хотите.
  • Вместо того, чтобы добавлять границу к обязательным элементам, я предлагаю Вы также добавляете текст, чтобы сказать, в чем проблема.

// getting all forms in the page you can also get specific forms based on their class-name
var forms = document.getElementsByTagName('form'),
  l = forms.length,
  i = 0;
// adding submit submit event listener to the referenced forms
for(; i < l; i++) {
  forms[i].addEventListener('submit', validateForm);
}


function validateForm(e) {
  var els = this.querySelectorAll('input.required'),
    len = els.length,
    err = false,
    c = 0,
    inpName = '';
  // checking if the form has a select, if so, allow only the select or the input to be filled
  var isSelect = this.getElementsByTagName('select');
  if(isSelect[0] !== undefined && isSelect[0] !== null) {
    var inp = isSelect[0].parentNode.nextElementSibling.querySelector('input.required');
    inpName = inp.name;
    if((isSelect[0].value == '' && inp.value.trim().length === 0) || (isSelect[0].value != '' && inp.value.trim().length > 0)) {
      err = true;
      isSelect[0].classList.add("warning");
      inp.classList.add("warning");
    } else {
      isSelect[0].classList.remove("warning");
      inp.classList.remove("warning");
    }
  }

  // iterate through the rest of the inputs and check for empty one, thus trimming them before checking
  for(; c < len; c++) {
    if(els[c].name !== inpName) {
      if(els[c].value.trim() == '') {
        err = true;
        els[c].classList.add("warning");
      } else {
        els[c].classList.remove("warning");
      }
    }
  }
  // based on the error variable, either submit the form or cancel submission
  (!err) ? this.submit():e.preventDefault();
}
.warning {
  border: 2px solid red;
}
<form method="post">
    <div class="form-group">
        <label>Product Name</label>
        <input class="form-control required" type="text" name="product" />
    </div>
    <div class="form-group">
        <select class="form-control required" id="category" name="category[]">
            <option value="">Select Existing Category</option>
            <option value="Shirts">Shirts</option>
            <option value="Shoes">Shoes</option>
            <option value="Pants">Pants</option>
        </select>
    </div>
    <div class="form-group">
        <label>Create New Category</label>
        <input class="form-control required" type="text" name="category[]" />
    </div>
    <div class="form-group">
        <input class="btn btn-primary" type="submit" value="Submit" />
    </div>
</form>

Надеюсь, я подтолкнул тебя дальше.

Может появиться сообщение: «Пользовательский модуль ошибок не распознать эту ошибку. ", когда вы успешно отправили форму из фрагмент выше, что из-за ограничений StackOverflow, поскольку они не разрешать / серверный код (StackOverflow не позволяет форме быть представлен).

...