Yii2: проверка формы ajax на представленной форме ajax
Мне интересно, могут ли какие-либо эксперты Yii2 помочь мне понять, как лучше всего работать с формами ajax в сочетании с валидацией Yii ajax. Думаю, я могу объяснить проблему, не пропустив весь мой код.
Я работаю над формой ввода промо-кода, в которой пользователь вводит свой промо-код в форму, форма отправляется через ajax. Затем мы выполняем поиск базы данных для деталей промо-кода, проверяем код и, если код проверяется, мы хотим отобразить регистрационную форму, которая скрыта на странице.
У меня есть специальная функция проверки для поля формы "code", которая является активным полем в модельном сценарии с именем "register".
class UserCode extends ActiveRecord
{
...
public function scenarios()
{
return [
'register' => ['code'],
];
}
public function rules()
{
return [
[['code'], 'required'],
[['code'], 'validateUserCode', 'on' => ['register']],
];
}
public function validateUserCode($attribute, $params)
{
// perform all my custom logic to determine if the code is valid
if ($code_invalid) {
$this->addError($attribute, 'Sorry, this code is invalid.');
}
}
...
}
Затем в контроллере, как предлагает Yii2 Guide, я задерживаю эту проверку ajax следующим кодом:
public function actionValidate() {
$model = new UserCode(['scenario' => 'register']);
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
// no logic can be run after the above code b/c the form is submit with ajax
// and therefore always trapped in the Yii::$app->request->isAjax conditional
}
Приведенный выше код работает отлично, и если я удаляю фокус из поля $form->field($model, 'code')
в моей форме, выполняется проверка Yii ajax и выводит мое пользовательское сообщение об ошибке на основе моей пользовательской логики проверки.
Моя задача возникает, когда я отправляю форму. Подача формы также обрабатывается через ajax, и поэтому действие контроллера всегда возвращает результат ActiveForm::validate($model);
, потому что if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post()))
будет применяться как к валидации формы ajax, так и к форме submit.
С приведенным выше подходом я вынужден возвращать только результаты проверки ajax, а не любые json-данные, которые могут понадобиться для дополнительной проверки на стороне клиента, например, отображение регистрационной формы после того, как действительный код использования отправлен через ajax.
Я понимаю, что я могу установить 'enableAjaxValidation' => false
в ActiveForm, а затем вернуть свои собственные данные json внутри условия if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post()))
. Если я это сделаю, я могу показать регистрационную форму, потому что у меня есть свои собственные данные json для работы.
Есть ли способ иметь ajax-проверку в форме, представленной с помощью ajax? Как вы могли бы отследить проверку ajax отдельно от представления формы ajax для обработки двух событий разными способами?
Любые предложения или альтернативные подходы высоко ценятся!
Ответы
Ответ 1
Вы должны настроить validationUrl
с другим URL-адресом по сравнению с URL-адресом, которому вы отправляете форму. Таким образом, вы можете иметь функцию проверки, которая будет проверять и возвращать return ActiveForm::validate($model);
и нормальную форму отправки, которая делает что-то еще.
Подробнее о validationUrl
здесь:
Ответ 2
Я нашел решение:
Форма:
<?php
$form = ActiveForm::begin(['id' => 'form-add-contact', 'enableAjaxValidation' => true, 'validationUrl' => Yii::$app->urlManager->createUrl('contacts/contacts/contact-validate')]);
?>
Отправить через Ajax:
<?php
$script = <<< JS
$(document).ready(function () {
$("#form-add-contact").on('beforeSubmit', function (event) {
event.preventDefault();
var form_data = new FormData($('#form-add-contact')[0]);
$.ajax({
url: $("#form-add-contact").attr('action'),
dataType: 'JSON',
cache: false,
contentType: false,
processData: false,
data: form_data, //$(this).serialize(),
type: 'post',
beforeSend: function() {
},
success: function(response){
toastr.success("",response.message);
},
complete: function() {
},
error: function (data) {
toastr.warning("","There may a error on uploading. Try again later");
}
});
return false;
});
});
JS;
$this->registerJs($script);
?>
Контроллер:
/*
* CREATE CONTACT FORM AJAX VALIDATION ACTION
*/
public function actionContactValidate() {
$model = new ContactsManagement();
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
$model->company_id = Yii::$app->user->identity->company_id;
$model->created_at = time();
\Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
}
/**
* Quick Add Contact Action
* @param type $id
* @return type
*/
public function actionAddContact() {
$model = new ContactsManagement();
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($model->validate()) {
$flag = $model->save(false);
if ($flag == true) {
$transaction->commit();
return Json::encode(array( 'status' => 'success', 'type' => 'success', 'message' => 'Contact created successfully.'));
} else {
$transaction->rollBack();
}
} else {
return Json::encode(array('status' => 'warning', 'type' => 'warning', 'message' => 'Contact can not created.'));
}
} catch (Exception $ex) {
$transaction->rollBack();
}
}
return $this->renderAjax('_add_form', [
'model' => $model,
]);
}