ActiveForm и ajax validation

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
sda
Сообщения: 334
Зарегистрирован: 2013.12.19, 09:29

ActiveForm и ajax validation

Сообщение sda »

Здравствуйте. Пытаюсь использовать аякс валидацию, чуть иначе, чем описано здесь, а именно вот так

Код: Выделить всё

    public function actionCreate()
    {
        $model = new RoleForm;
        $this->performAjaxValidation($model);
        if ($model->load(Yii::$app->request->post())) {
            ...
        }
        return $this->render('create', ['model' => $model]);
    }
    
    protected function performAjaxValidation($model)
    {
        if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ActiveForm::validate($model);
        }
    }
Но это не работает, в ответ на ajax-запрос приходит вся html-страница. Работает только так как пишут в доках по yii2, то есть вот так

Код: Выделить всё

    public function actionCreate()
    {
        $model = new RoleForm;
        if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ActiveForm::validate($model);
        }
        if ($model->load(Yii::$app->request->post())) {
            ...
        }
        return $this->render('create', ['model' => $model]);
    }
Но проблема в том, что такой способ ведет к дублированию кода. Поэтому я пытаюсь вынести всё в performAjaxValidation, но это упорно отказывается работать. Как можно решить?

Спасибо. Версия 2.0.1
dmeroff
Сообщения: 101
Зарегистрирован: 2012.06.05, 14:32
Откуда: Петрозаводск
Контактная информация:

Re: ActiveForm и ajax validation

Сообщение dmeroff »

Вот так, к примеру:

Код: Выделить всё

/**
* Performs ajax validation.
* @param Model $model
* @throws \yii\base\ExitException
*/
protected function performAjaxValidation(Model $model)
{
    if (\Yii::$app->request->isAjax && $model->load(\Yii::$app->request->post())) {
        \Yii::$app->response->format = Response::FORMAT_JSON;
        echo json_encode(ActiveForm::validate($model));
        \Yii::$app->end();
    }
}
 
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: ActiveForm и ajax validation

Сообщение zelenin »

ну оно и не будет работать, потому что нужно использовать так, как в доках. а так как вы написали, прерывания на performAjaxValidation не будет, потому что => учите php.
А вот свой урл задать для валиадции можно, чтобы форма обращалась не наобщий экшн, а специальный для валидации.
sda
Сообщения: 334
Зарегистрирован: 2013.12.19, 09:29

Re: ActiveForm и ajax validation

Сообщение sda »

dmeroff писал(а):Вот так, к примеру:

Код: Выделить всё

/**
* Performs ajax validation.
* @param Model $model
* @throws \yii\base\ExitException
*/
protected function performAjaxValidation(Model $model)
{
    if (\Yii::$app->request->isAjax && $model->load(\Yii::$app->request->post())) {
        \Yii::$app->response->format = Response::FORMAT_JSON;
        echo json_encode(ActiveForm::validate($model));
        \Yii::$app->end();
    }
}
 
Да спасибо, это работает.
zelenin писал(а):ну оно и не будет работать, потому что нужно использовать так, как в доках. а так как вы написали, прерывания на performAjaxValidation не будет, потому что => учите php.
А вот свой урл задать для валиадции можно, чтобы форма обращалась не наобщий экшн, а специальный для валидации.
Спасибо, да затупил, перечитал ман по возврату значений, действительно прерывания быть не может, но и как в доках использовать тоже не вариант. Сделаю, как делал в yii1, т.е. как выше предложил человек.
lynicidn
Сообщения: 2222
Зарегистрирован: 2014.05.24, 15:12

Re: ActiveForm и ajax validation

Сообщение lynicidn »

Код: Выделить всё

public function actionCreate()
    {
        $model = new RoleForm;
        if ($errors = $this->performAjaxValidation($model)) {
            return $errors;
        }
        if ($model->load(Yii::$app->request->post())) {
            ...
        }
        return $this->render('create', ['model' => $model]);
    }

    protected function performAjaxValidation($model)
    {
        if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ActiveForm::validate($model);
        }
    }
lynicidn
Сообщения: 2222
Зарегистрирован: 2014.05.24, 15:12

Re: ActiveForm и ajax validation

Сообщение lynicidn »

zelenin писал(а): echo json_encode(ActiveForm::validate($model));
\Yii::$app->end();
или так насильно закончить приложение, но лучше ретурном отдавать все от контроллера
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: ActiveForm и ajax validation

Сообщение zelenin »

lynicidn писал(а):
zelenin писал(а): echo json_encode(ActiveForm::validate($model));
\Yii::$app->end();
или так насильно закончить приложение, но лучше ретурном отдавать все от контроллера
больше хаков! больше!

Я же написал: отдельный экшн и строчка в конфиге формы. Все уже придумано.
sda
Сообщения: 334
Зарегистрирован: 2013.12.19, 09:29

Re: ActiveForm и ajax validation

Сообщение sda »

zelenin писал(а):
lynicidn писал(а):
zelenin писал(а): echo json_encode(ActiveForm::validate($model));
\Yii::$app->end();
или так насильно закончить приложение, но лучше ретурном отдавать все от контроллера
больше хаков! больше!

Я же написал: отдельный экшн и строчка в конфиге формы. Все уже придумано.
Да, спасибо, только хотел отписать :D . В API ActiveForm, оказывается есть $validationUrl. Всё встало на свои места.
abr-ya
Сообщения: 17
Зарегистрирован: 2019.08.11, 21:29

Re: ActiveForm и ajax validation

Сообщение abr-ya »

И ещё немного некропостинга.
После включения Ajax-валидации по документации:
https://www.yiiframework.com/doc/guide/ ... validation
Форма начинает отправляться как только input теряет фокус. Это можно как-то отключить-настроить, или это говорит о том, что у меня ошибка в коде и надо проводить раскопки?)
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: ActiveForm и ajax validation

Сообщение yiiliveext »

abr-ya писал(а): 2019.08.27, 10:42 И ещё немного некропостинга.
После включения Ajax-валидации по документации:
https://www.yiiframework.com/doc/guide/ ... validation
Форма начинает отправляться как только input теряет фокус. Это можно как-то отключить-настроить, или это говорит о том, что у меня ошибка в коде и надо проводить раскопки?)
Возможно. Для начала отключите клиентскую валидацию

Код: Выделить всё

 'enableClientValidation' => false
Отключить валидацию при потере фокуса можно установив

Код: Выделить всё

'validateOnBlur' => false
Еще есть

Код: Выделить всё

'validateOnChange' => true, // при изменении поля 
'validateOnType' => true //при наборе в поле
abr-ya
Сообщения: 17
Зарегистрирован: 2019.08.11, 21:29

Re: ActiveForm и ajax validation

Сообщение abr-ya »

Спасибо!
Не помогает в любых сочетаниях.
На всякий случай уточню: у меня все происходит в модалке и с помощью renderAjax.
И по потере фокуса у меня проходит валидация, и если проходит - обновляются данные.

Я хотел бы, чтобы валидация так и работала, но сохранение-закрытие при этом не происходило, пока пользователь сам не нажмет "Save".
Указанные же выше опции привели к тому, то данные не сохраняются и модалка не закрывается если форма не проходит валидацию.
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: ActiveForm и ajax validation

Сообщение yiiliveext »

Вам нужно все три опции выставить в false

Код: Выделить всё

'validateOnBlur' => false,
'validateOnChange' => false, 
'validateOnType' => false, // false by default
abr-ya писал(а): 2019.08.27, 11:52 Указанные же выше опции привели к тому, то данные не сохраняются и модалка не закрывается если форма не проходит валидацию.
Так в этом же и есть смысл валидации, не?))
abr-ya
Сообщения: 17
Зарегистрирован: 2019.08.11, 21:29

Re: ActiveForm и ajax validation

Сообщение abr-ya »

yiiliveext, спасибо за помощь!
Может я не совсем точно выражаюсь.
Мне кажется, что валидация - это проверка и указание на ошибку.
Сохранение - это запись в база и рендер или редирект, в моем случае - редирект.
У меня они смешались.
Т.е. как только проходит валидация по потере фокуса, тут же происходит сохранение (а у меня при этом закрывается модалка).

В идеале, сохранить валидацию, но без нажатия кнопки не проихводить запись в БД и не закрывать модалку.
Но наверное могут быть и другие варианты.
Надеюсь, сейчас достаточно точно описал свою проблему.
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: ActiveForm и ajax validation

Сообщение yiiliveext »

Тогда у вас проблема в контроллере. Приведите код.
urichalex
Сообщения: 994
Зарегистрирован: 2015.08.07, 11:03

Re: ActiveForm и ajax validation

Сообщение urichalex »

В контроллере не ловите запрос на валидацию. А именно

Код: Выделить всё

if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
    Yii::$app->response->format = Response::FORMAT_JSON;
    return ActiveForm::validate($model);
}
abr-ya
Сообщения: 17
Зарегистрирован: 2019.08.11, 21:29

Re: ActiveForm и ajax validation

Сообщение abr-ya »

Спасибо за ответы, не сразу увидел.
Похоже, я запутался.

Попробую описать, что у меня сейчас, очень хочется понять, в каком порядке правильно действовать, а не просто скопипастить код.

Что мне надо проверять в первую очередь?
Что запрос на Ajax, что пришли post-данные? Что пришли данные и они записаны?

Сейчас для формы я установил:

Код: Выделить всё

        'enableAjaxValidation' => true,
        'enableClientValidation' => false,
        'validateOnBlur' => false,
        'validateOnChange' => false, 
        'validateOnType' => false,
В контроллере у меня происходит следующее:

Код: Выделить всё

        // если запись обновлена
        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['index']);
        }

        // если запрос на аяксе
        if(Yii::$app->request->isAjax) {
            // если есть новые данные
            if ($model->load(Yii::$app->request->post())) {
                Yii::$app->response->format = Response::FORMAT_JSON;
                return ActiveForm::validate($model);
            } else {
                // первое открытие формы
                return $this->renderAjax('_formAjax', compact('model', 'users', 'types'));
            }             
        } else {
            return $this->render('update', compact('model', 'users', 'types'));
        }
Работает почти во всех случаях, но:
- отключена валидация Ajax - неудобно,
- данные кнопкой Save сохраняются и модалка закрывается только если форма проходит валидацию, если не проходит - просто висит модалка.

Как бы я хотел:
- валидация на лету работает,
- при снятии фокуса с поля валидация происходит, но не запись данных!
- при нажатии кнопки Save происходит запись.

Буду благодарен за совет, как это все правильно проверять и в каком порядке?!

UPD:
Как только включаю enableClientValidation любое изменение в модалке, даже выбор другого значения в select, приводит к записи данных и закрытию модалки.
abr-ya
Сообщения: 17
Зарегистрирован: 2019.08.11, 21:29

Re: ActiveForm и ajax validation

Сообщение abr-ya »

Возник такой вопрос: как правильно в контроллере отследить, что было нажатие кнопки Save, и только в этом случае выполнять метод save()?
А то у меня сейчас получается, что в любом случае выполняется save(), где надо, и где не надо!
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: ActiveForm и ajax validation

Сообщение ElisDN »

Сделать отдельный validateAction.
abr-ya
Сообщения: 17
Зарегистрирован: 2019.08.11, 21:29

Re: ActiveForm и ajax validation

Сообщение abr-ya »

ElisDN писал(а): 2019.09.03, 13:54 Сделать отдельный validateAction.
Можно хоть небольшой толчок в направлении: как это правильно определить-разнести?
Как у меня контроллер должен понять, когда мне нужна валидация на лету, а когда кнопку save нажали и надо сохранять и закрывать модалку?

Сейчас у меня во вьюхе форма в модалку грузится следующим образом:

Код: Выделить всё

$('#modalID').find('.modal-body').load('/web/service/update?id=' + data.key);
Кажется, уже понял, что save() в моем экшене и путает мне всё.

Но пока что-то не пойму, как всё же разнести валидацию и сейв, чтобы все работало логично и красиво?
abr-ya
Сообщения: 17
Зарегистрирован: 2019.08.11, 21:29

Re: ActiveForm и ajax validation

Сообщение abr-ya »

Всем спасибо за помощь! Кажется, заработало, хотя разобраться как следует с этой темой всё равно стоит.
Не знаю: читал я невнимательно, или дергал из разных источников информацию, или просто глаз замылился, но.
Форма начала вести себя именно так, как мне хотелось бы, когда я убрал из её бегина вот этот параметр:

Код: Выделить всё

'enableAjaxValidation' => true,
Как оказалось, это совершенно не мешает валидации "на лету" от фреймворка!
Наверное, надо больше внимания уделять чтению документации!)
Ответить