Решено, ответ ниже
Всем привет, уважаемые знатоки) разжуйте кому не лень плз, как правильно ActiveForm ajax-ом отправлять, немного запутался в способах.
Есть форма
<?php $form = ActiveForm::begin([
'options' => [
'id' => 'product-form',
'enableAjaxValidation' => true
]
]); ?>
Нужно отправить форму ajax-ом, и если модель сохранена отрендрить другую вьюху вместо формы, без перезагрузки.
Как пробовал решать
1. Прописать в модели 'beforeSubmit' (Нашел где-то на форуме);
<?php $form = ActiveForm::begin([
'beforeSubmit' => new \yii\web\JsExpression('function(form) {
jQuery.ajax({
url: "'. $this->context->createUrl('create') .'",
type: "POST",
dataType: "json",
data: form.serialize(),
success: function(response) {
...
},
error: function(response) {
...
}
});
return false;
}')
]);
На что получил в ответ, ActiveForm не знает значения 'beforeSubmit';
2.Прописал почти тоже самое и зарегистрировал в js блоке.
$(document).on("beforeSubmit", "#product-form", function () {
var form = $(this).serialize();
jQuery.ajax({
type: 'POST',
url: "/admin/feed/save",
data: {forma: form},
dataType: "json",
success: function (data) {
alert(data);
},
error: function (data) {
alert('беда');
}
});
});
И все равно столкнулся с проблемами
a)Запрос все время возвращается ерорсами, хотя в логах все чисто( при этом логики в обработчике не прописано, просто return "ок"; пока что. запрос не пустой.
b)Сначала выполняется "beforeSubmit"; Потом идет действие обработчика с которого собственно вызвана форма, синхронно, то есть даже если Ajax сохранит форму, то она все равно улетает в свой обработчик и куда-то редиректит, как в форме указать что только ajax запрос должен работать?
c) И самое главное, как лучше принять данные из формы и обработать? Чтоб все собрать использую serialize(), и в JSON-e отправляю, как это на сервере принять и обработать, с учетом того что мне html нужно вернуть, если succes: вид со всеми товарами, если error: форму с отображенными ерорсами. Кому не лень разъясните или ткните носом где почитать об этом подробней плз, а то с ajax ActiveForm первый раз работаю. Заранее спасибо)
Решение$script = <<< JS
$(document).on("beforeSubmit", "#product-form", function () {
//Сама форма
var form = $(this);
$.ajax({
//Тип запроса
type: form.attr('method'),
//Адрес запроса
url: form.attr('action'),
//Данные из формы в массиве
data: form.serializeArray(),
}
)
//Если запрос отправлен
.done(function(data) {
//Не прошла валидация с сервера
if (data.validation) {
form.yiiActiveForm('updateMessages', data.validation, true); // renders validation messages at appropriate places
} else {
//Рендр полученного шаблона в блок вместо формы(в моем случае список продуктов)
jQuery('.my_own_info').html(data);
window.history.replaceState('admin', null, '/admin/feed/my-products')
}
})
//Если запрос не ушел
.fail(function () {
alert('Ошибка, попробуйте позже');
})
return false; // Отменить синхронную отправку данных
});
JS;
$this->registerJs($script);
?>
в контроллере:
//Если пришел Ajax запрос
if (Yii::$app->request->isAjax) {
//Если объект создан
if ($model->load(Yii::$app->request->post()) && $model->save()) {
//Вернуть нужныйй шаблон хтмл
$products = Product::find()->all();
return $this->renderAjax('my_products', compact($products));
}
$result = [];
//если валидация модели не прошла, собираем ошибки, и возвращаем
foreach ($model->getErrors() as $attribute => $errors) {
$result[Html::getInputId($model, $attribute)] = $errors;
}
return $this->asJson(['validation' => $result]);
}