Yii2, как запустить валидацию формы вручную и получить результат?

Добрый день.
Возникла проблема.

У меня есть визард, в визарде в одном из шагов используется форма ActiveForm.
Перед тем, как переходить к следующему шагу, я хочу запустить валидацию формы вручную.
Если смотреть код из yii.activeForm.js, то в теории это должно делаться так:
var $form = $('#profile-form');	
$('#profile-form').yiiActiveForm('validate');


метод запускается, отваливается на внутренней проверке валидации атрибута:
if (data.submitting || this.status === 2 || this.status === 3) {...}


есть альтернативный вариант, запускать вручную валидацию каждого поля формы и по результатам валидации уже переходить к следующему шагу визарда:
$('#profile-form').yiiActiveForm('validateAttribute', 'profileform-email');

но мне не нравится что код выходит несколько громоздким.

как правильно запустить валидацию формы вручную?
  • Вопрос задан
  • 13480 просмотров
Решения вопроса 1
monax-at
@monax-at Автор вопроса
Используется yii2, дополнительная библиотека для gui - fuelux
Решение такое.
Вешаю калбек на переход на следующий элемент визарда, если заходит в список то останавливаю переход на следующий элемент и запускаю валидацию:
$('#cart-wizard').on('actionclicked.fu.wizard', function(evt, data) {
	if(data.direction !== 'next') {return;}
	if(data.step === 2) {
		Cart.runValidation();
		return false;
	}			
}

Прохожусь по заранее сформированному массиву с айдишниками валидируемых полей и вручную запускаю валидацию через yiiActiveForm.
runValidation: function () {
		Cart.profileValidator.validations = [];
		var form = $(Cart.profileValidator.formSelector);
		for(var key in Cart.profileRows) {
			form.yiiActiveForm('validateAttribute', Cart.profileRows[key]);
		}
	},

Далее вешаю калбек на событие валидации каждого нужного поля формы.
Когда все поля будут провалидированы - проверяю есть ли ошибки и если нет - совершаю переход на следующий шаг визарда:
$(Cart.profileValidator.formSelector).on('afterValidateAttribute', function (event, attribute, messages) {
			Cart.profileValidator.validations.push({
				id: attribute.id,
				message: messages[0]
			});
			if (Cart.profileRows.length != Cart.profileValidator.validations.length) {
				return;
			}			
			var hasError = false;
			for(var key in Cart.profileValidator.validations) {
				if (Cart.profileValidator.validations[key].message != undefined ) {
					hasError = true;						
					break;
				}
			}
			if (!hasError) {
				$('#cart-wizard').wizard('selectedItem', {
					step: 3
				});					
			}			
		});
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
webinar
@webinar Куратор тега Yii
Учим yii: https://youtu.be/-WRMlGHLgRg
Тут надо понимать Ваш визард. Он через контроллер работает или он на javascript?
Почитайте про ajax валидацию форм в yii2, например тут: coderlife.eu/php/sozdanie-ajax-validacii-na-primer...
Ответ написан
@IStrangerX
Вопрос давнишний, но тем не менее опубликую свой вариант решения (с помощью эмулирования отправки формы).
Нативная реализация не позволяет гибко управлять реализацией валидации форм на клиенте - всё слишком заточено на отправку одной формы.

var validationEnabled = false,
    $form             = $('#form_id');

/**
 * Validates form.
 * Note: after first successful validation of form this state of form will be cached (this is yii.activeForm.js-native feature).
 * @param {Function} callback Function as first argument passes result of validation.
 */
function validateForm(callback) {

    if (!validationEnabled) {
        $form.on('submit', function () {
            var $form       = $(this),
                yiiFormData = $form.yiiActiveForm('data');

            callback(yiiFormData.validated);

            return false;                   // we stop submitting of form (we submit only for performing of validation)
        });

        validationEnabled = true;           // don't use of .one(handler), because it can't prevent form submitting
    }


    $form.trigger('submit');    // this runs validation of form
}


// ... do something


validateForm(function (successValidated) {
    if (successValidated) {
        // ... do something
    }
});


* Можно конечно еще проще обмануть виджет, типа форма отправилась (но там результат валидации выковыривать сложнее):

$form.yiiActiveForm('data').submitting = true;
$form.yiiActiveForm('validate');
Ответ написан
Комментировать
@pun200648
Понимаю, что пост старый.
Но сам столкнулся с данной задачей.
Она была решена в коммите https://github.com/ptolomaues/yii2/commit/22d7c57f....

Вкратце.
form = $('#someForm');
form.data('yiiActiveForm').validate_only = true;
form.one('afterValidate', afterValidateEvent);
form.yiiActiveForm('validate', true); //run validation

function afterValidateEvent() {
    if ($('#someForm').find('.has-error').length) {
       // Validation failed
    }
     // Validation successed
}


В этом случае сабмит формы не происходит, а результат можно забрать с события afterValidate.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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