Как правильно проверить форму Twitter Bootstrap на нескольких вкладках с помощью jQuery Validate?

У меня есть одна форма, расположенная на нескольких вкладках Twitter Bootstrap:

<form id="personal-data" class="form-horizontal">
  <div class="tabbable">
    <ul id="tab" class="nav nav-tabs">
      <li class="active"><a href="#home" data-toggle="tab">Home</a></li>
      <li class=""><a href="#profile" data-toggle="tab">Profile</a></li>
      <!-- ... -->
    </ul>

    <div id="myTabContent" class="tab-content">
      <div class="tab-pane fade active in" id="home">
        <fieldset>
          <div class="control-group">
            <div class="controls">
              <input type="text" id="field1">
            </div>
          </div>
        </fieldset>
      </div>
      <div class="tab-pane fade" id="profile">
        <fieldset>
          <div class="control-group">
            <div class="controls">
              <input type="text" id="field2">
            </div>
          </div>
        </fieldset>          
      </div>

Когда я valid использовал форму с проверкой jQuery на активной вкладке и поле с недопустимым значением на одной и той же вкладке, то проверка не выполняется (это правильно). Но когда я нахожусь на одной вкладке, а недопустимое значение - на другой вкладке, то проверка возвращает true, что неверно. Как я могу это исправить? Как я могу выделить это поле на другой вкладке?

См. эту демонстрационную версию (просто нажмите кнопку дальше - появится сообщение об ошибке, затем перейдите к последней вкладке и нажмите здесь).

Ответ 1

Я думаю, ваша проблема заключается в том, что валидация происходит только в видимых элементах.

Считая это issue, мы видим, что в версии 1.9

Исправлено # 189 -: скрытые элементы теперь игнорируются по умолчанию

и решение несколько комментариев вниз

$.validator.setDefaults({
    ignore: ""
});

Ответ 2

Мое решение включить вкладки

...
highlight: function(label) {
        $(label).closest('.control-group').addClass('error');

        $(".tab-content").find("div.tab-pane:hidden:has(div.error)").each( function(){
            var id = $(this).attr("id");
            $('#tabs a[href="#'+id+'"]').tab('show');
        });
},
...

Необходимо добавить этот код, чтобы разрешить вкладку изменения js

$('a[data-toggle="tab"]').on('shown', function (e) {
  e.target // activated tab
  e.relatedTarget // previous tab
});

Ответ 3

спасибо за ваш код, он решил большую часть моей проблемы, за исключением части, чтобы перейти к первой вкладке с ошибкой. Я обошел следующим образом:

        var IsValid = true;

        // Validate Each Bootstrap tab
        $(".tab-content").find("div.tab-pane").each(function (index, tab) {
            var id = $(tab).attr("id");
            $('a[href="#' + id + '"]').tab('show');

            var IsTabValid = $("#SomeForm").valid();

            if (!IsTabValid) {
                IsValid = false;
            }
        });

        // Show first tab with error
        $(".tab-content").find("div.tab-pane").each(function (index, tab) {
            var id = $(tab).attr("id");
            $('a[href="#' + id + '"]').tab('show');

            var IsTabValid = $("#SomeForm").valid();

            if (!IsTabValid) {
                return false; // Break each loop
            }
        });

Ответ 4

Используются ли эти вкладки jQuery? Вы можете деактивировать все остальные вкладки и постепенно активировать их, пока представленные данные в каждой форме проходят проверку. Отключите их все, кроме первого в вашем конструкторе, и после каждой проверки активируйте следующую.

.tabs( "enable" , index )

Подробнее здесь.

В конце вы также можете поместить один окончательный метод проверки и поместить весь свой контент в зависимости от вкладок, чтобы вы могли избежать перезагрузки ссылок.

Ответ 5

Основываясь на @juanmanuele answer, вот как мне удалось заставить его работать с Bootstrap 3 вкладки:

if($(".tab-content").find("div.tab-pane.active:has(div.has-error)").length == 0)
{
    $(".tab-content").find("div.tab-pane:hidden:has(div.has-error)").each(function(index, tab)
    {
        var id = $(tab).attr("id");

        $('a[href="#' + id + '"]').tab('show');
    });
}

Чтобы сосредоточить внимание на первом входе с ошибкой:

$('a[data-toggle="tab"]').on('shown.bs.tab', function(e)
{
     e.target // activated tab

     $($(e.target).attr('href')).find("div.has-error :input:first").focus();

     //e.relatedTarget // previous tab
});

Ответ 6

Не точно решение для jQuery Validate, но вы можете использовать "недействительное" событие в элементах формы, чтобы уловить ошибки проверки HTML5 и получить сфокусированный элемент, найти соответствующую вкладку и показать ее.

Я сделал это.

$("form").find("input, select").on("invalid", function() {
  var id = $(this).parents(".tab-pane").attr("id");

  $("#tabs-selector ul").find("li a[href='#" + id + "']").tab("show");
});

Надеюсь, это поможет вам. Опять же, это для HTML5 или если jQuery Validate вызывает недопустимое событие.