Валидация при определенном значении атрибута в форме загружаемой через pjax

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
yura1976
Сообщения: 134
Зарегистрирован: 2012.08.06, 13:24

Валидация при определенном значении атрибута в форме загружаемой через pjax

Сообщение yura1976 »

Есть 2 кнопки (фактически радиокнопки) "Физическое лицо" и "Юр. лицо". При клике на одну из них должна подгружаться форма с соответствующими параметрами. Модель одна - Companies. В форме для физ. лиц поле fio - обязательно, в форме для юр. лиц поля name и ownership_id - обязательные. Приведу свой код и после него формулировку вопроса. Если посчитаете мою реализацию совсем кривой (даже в той части, которая не относится к сути), прошу подсказать как лучше, может быть в виде ссылки на то как нужно, ну или хотя бы просто навести на мысль. Буду рад любой критике.
В представлении я это реализовал так:

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

	
<?php Pjax::begin(['id' => 'choosingForm']); ?>
<?php
$form = ActiveForm::begin([
    'id' => 'companycreate-form',
            'enableAjaxValidation' => true,
            'enableClientValidation' => true, 
            'validationUrl' => \yii\helpers\Url::to(['validate-form']),
            'options' => ['enctype' => 'multipart/form-data'],
        ]); 
?>
<?= $form->field($model, 'of', ['inline'=>true, 'enableLabel'=>false])
        ->radioList([
            '1'=>Yii::t('companies','PRIVATE_PERSON_TITLE'),
            '2'=>Yii::t('companies','COMPANY_PERSON_TITLE'),
        ], [
            'id' => 'of-radio',
            'class' => 'btn-group',
            'data-toggle' => 'buttons',
            'unselect' => null,
            'item' => function ($index, $label, $name, $checked, $value) {
                return '<label id="btn_of'.$value.'" class="lbl_of btn btn-orange' . ($checked ? ' active' : '') . '"> ' .
                    Html::radio($name, $checked, ['value' => $value, 'class' => 'company_of-btn']) . ' ' . $label . '</label>';
            },
        ]);
?>
</div>
<?php if(isset($model->of)) {  ?>
<div class="col-md-12" id="choosingform">
    <?php echo $this->render('_form'.$model->of.'.php',['form'=>$form,'model'=>$model]); ?>
</div>
<?php } ?>
    <?php ActiveForm::end(); ?>
    <?php Pjax::end(); ?>
$model->of = 1 - это значит физ. лицо, $model->of=2 - юр. лицо
Соответственно в зависимости от того что выберет пользователь, подгружается либо вьюха _form1.php либо _form2.php

В модели:

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

 
public function rules()
    {      
        return [
            [['fio'], 'required', 'when' => function($model) {
                    return $model->of == '1';
                }
            ], 
            [['ownership_id'], 'required', 'when' => function($model) {
                    return $model->of == '2';
                }, 'message' => Yii::t('companies','VALIDATE_ERROR_OWNERSHIP')], 
            [['name'], 'required', 'when' => function($model) {
                    return $model->of == '2';
           }], 
           .....
   }
В контроллере:

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

    public function actionCreate()
    {
            $model = new Companies();
            if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
            	if($model->validate() && $model->of){
			.....
			$model->save();
		}
		return $this->redirect(['view', 'slug' => $model->slug]);
            }
            else{
		if(!isset($model->of) && NULL !== Yii::$app->request->get('of')){
                	$model->of = Yii::$app->request->get('of');
            	}
                 return $this->render('create', [
                    'model' => $model,
                ]);
            }
    }

    public function actionValidateForm() 
    {
        if (Yii::$app->request->isAjax) {
            Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
            $model = new Companies();
            if($model->load(Yii::$app->request->post()))
                return \yii\widgets\ActiveForm::validate($model);
        }
        throw new \yii\web\BadRequestHttpException('Bad request!');
    }
JS:

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

  $('.companies-form').on('click','.lbl_of',function(e){
    var lbl_id = $(this).attr('id');
    var options = $('#'+lbl_id+' input').val();
    $.pjax({
      type       : 'GET',
          url        : 'companies/create',
          container  : '#choosingForm',
          data       : {'of':options},
          push       : true,
          replace   : false,
          timeout   : 10000,
          scrollTo   : false
    });
    
Проблема в следующем. Если пользователь кликает на "Юр. лицо", то форма не подгружается. В консоли отображается:

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

{"companies-fio":["Необходимо заполнить «Фамилия и имя»."], .... }
Т.е., при наличии ошибки валидации одной из двух форм нельзя переключаться между этими формами. Как решить проблему? Что я делаю не так?
masson
Сообщения: 545
Зарегистрирован: 2012.07.03, 15:59

Re: Валидация при определенном значении атрибута в форме загружаемой через pjax

Сообщение masson »

1. В контроллере видимо неверное условие if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
тут вроде надо if !Yii::$app->request->isAjax, да?
2. Я бы вообще не стал с аяксом заморачиваться, а вывел бы 2 дива, в одном инпут с fio, в другом инпуты name и ownership_id и по клику один бы скрывал а другой показывал.
3. И обрабатывал бы не on('click','.lbl'), a on('change', 'input')
4. А может enableAjaxValidation тут не нужен?
yura1976
Сообщения: 134
Зарегистрирован: 2012.08.06, 13:24

Re: Валидация при определенном значении атрибута в форме загружаемой через pjax

Сообщение yura1976 »

masson писал(а): 2019.06.10, 21:32 1. В контроллере видимо неверное условие if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
тут вроде надо if !Yii::$app->request->isAjax, да?
В принципе если в методе actionValidateForm() есть "if (Yii::$app->request->isAjax)", то в условии, которое Вы пишете, что оно не верное, можно, думаю, вообще убрать "Yii::$app->request->isAjax && "
masson писал(а): 2019.06.10, 21:32 2. Я бы вообще не стал с аяксом заморачиваться, а вывел бы 2 дива, в одном инпут с fio, в другом инпуты name и ownership_id и по клику один бы скрывал а другой показывал.
Я привел только часть полей формы только чтобы описать саму проблему. На самом деле полей больше (там есть реквизиты компании из нескольких полей (ОГРН, ИНН, КПП, Наименование банка и т.п.), есть и еще другие поля, характерные для каждой из двух форм), поэтому "по клику один бы скрывал а другой показывал" - думаю, не лучший вариант, к тому же не понятно как он решит мою проблему с валидацией.
masson писал(а): 2019.06.10, 21:32 3. И обрабатывал бы не on('click','.lbl'), a on('change', 'input')
В данном случае результат работы вроде тот же. Или я торможу (что не исключено)?
masson писал(а): 2019.06.10, 21:32 4. А может enableAjaxValidation тут не нужен?
Закомментировал строку " 'enableAjaxValidation' => true,". К сожалению, это проблему не решило.
Последний раз редактировалось yura1976 2019.06.10, 23:30, всего редактировалось 1 раз.
yura1976
Сообщения: 134
Зарегистрирован: 2012.08.06, 13:24

Re: Валидация при определенном значении атрибута в форме загружаемой через pjax

Сообщение yura1976 »

Все заработало. Проблема оказалась в моей невнимательности

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

Pjax::begin([
        'id' => 'choosingForm',
    ]);
 
и

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

<div class="col-md-12" id="choosingform"> ... </div>
Имена id воспринимались как одинаковые.
masson
Сообщения: 545
Зарегистрирован: 2012.07.03, 15:59

Re: Валидация при определенном значении атрибута в форме загружаемой через pjax

Сообщение masson »

1. Зачем производится валидация при перерисовке формы?
2. Почему бы не определить Model->of в месте вызова actionCreate? Напр. Кнопка "Создать новую запись" с выпадающим списком - "Физ.лицо", "Юр.лицо" ... Тогда вообще все эти извраты с перерисовкой и аякс-валидациями не нужны будут. И кода будет раза в 2 меньше и сервак лишний раз дергать не надо.
yura1976
Сообщения: 134
Зарегистрирован: 2012.08.06, 13:24

Re: Валидация при определенном значении атрибута в форме загружаемой через pjax

Сообщение yura1976 »

masson писал(а): 2019.06.11, 09:11 1. Зачем производится валидация при перерисовке формы?
Вроде сейчас при перерисовке не производится (если я правильно понимаю). По крайней мере при переключении юр.лицо-физ.лицо ошибки валидации не появляются, переключение осуществляется корректно.
masson писал(а): 2019.06.11, 09:11 2. Почему бы не определить Model->of в месте вызова actionCreate? Напр. Кнопка "Создать новую запись" с выпадающим списком - "Физ.лицо", "Юр.лицо" ... Тогда вообще все эти извраты с перерисовкой и аякс-валидациями не нужны будут. И кода будет раза в 2 меньше и сервак лишний раз дергать не надо.
Мысль хорошая. Но заказчик хочет в виде именно кнопки-переключалки как я сделал. Переубедить его можно, но, честно говоря, я уже устал его переубеждать, времени на общение уходит много, причем довольно большая часть не по делу.
Ответить