Yii Framework Forum: Вопрос По Формам - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Вопрос По Формам Rate Topic: -----

#1 User is offline   melomaniac 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 182
  • Joined: 14-January 13

Posted 20 October 2013 - 10:12 PM

Всем доброе утро. Подскажите пожалуйста, можно ли разделить правила валидации для нескольких форм одной модели ? Т.е. чего имеем - есть 4 формы все они расположены в CJuiTabs, модель у них общая. И к примеру если на вкладке 1 у меня обязательное поле Имя, а на вкладке 2 - Фамилия, то к примеру форму с вкладки 2 не удастся отправить пока я не заполню Имя на вкладке 1, т.е. интересует можно ли с помощью сценариев разделить правила для разных форм одной модели. Грубый пример:

	public function rules()
	{
		return array(
                        if($form_id = form1){
			    array('name', 'required'),
                        }
                        if($form_id = form2){
			    array('surname', 'required'),
                        }
		);
	}


Вобщем принцип я думаю понятен :)
0

#2 User is offline   ORey 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,689
  • Joined: 20-April 09
  • Location:Moscow, Russia

Posted 20 October 2013 - 10:17 PM

Принцип понятен, вопрос непонятен :)
Да, это делается сценариями.
При создании формы, соответственно, просто указываете сценарий: $form1 = new YourModelForm('scenario1');
God is real unless declared as integer
1

#3 User is offline   tuschkan 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 122
  • Joined: 20-April 11
  • Location:Kiev, Ukraine

Posted 20 October 2013 - 10:25 PM

При сабмите формы при ajax валидации передает id. В таком случае нет необходимости инициировать 4 модели. Пример для ajax валидации.

        if (isset($_POST['ajax']) && $_POST['ajax'] === 'form1')
{
            $model->scenario='form1_scenario';
            $this->performAjaxValidation($model);
}

1

#4 User is offline   melomaniac 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 182
  • Joined: 14-January 13

Posted 20 October 2013 - 10:25 PM

View PostORey, on 20 October 2013 - 10:17 PM, said:

Принцип понятен, вопрос непонятен :)
Да, это делается сценариями.
При создании формы, соответственно, просто указываете сценарий: $form1 = new YourModelForm('scenario1');


А можно кусок кода наглядный ? :) Есть виджет CJuiTabs в нем 4 формы:

<?php $this->widget('zii.widgets.jui.CJuiTabs',array(
    'tabs'=>array(
        'Авто'=>$this->renderPartial("/forms/_autoform", array('model' => $model), $this),
        'Запчасти'=>$this->renderPartial("/forms/_sparesform", array('model' => $model), $this),
        'Услуги'=>$this->renderPartial("/forms/_servicesform", array('model' => $model), $this),
        'Обратная связь'=>$this->renderPartial("/forms/_feedbackform", array('model' => $model), $this),
    ),
    // additional javascript options for the tabs plugin
    'options'=>array(
        'collapsible'=>true,
    ),
)); ?>


Дык вот если я сделаю обязательными поля в форме _autoform и к примеру _sparesform, то отправить _autoform у меня не получится, пока я не заполню обязательные поля в форме _sparesform, а мне же нужно сделать их независимыми ::)
0

#5 User is offline   melomaniac 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 182
  • Joined: 14-January 13

Posted 20 October 2013 - 10:26 PM

View Posttuschkan, on 20 October 2013 - 10:25 PM, said:

При сабмите формы при ajax валидации передает id. В таком случае нет необходимости инициировать 4 модели. Пример для ajax валидации.

        if (isset($_POST['ajax']) && $_POST['ajax'] === 'form1')
{
            $model->scenario='form1_scenario';
            $this->performAjaxValidation($model);
}



Спасибо, сейчас гляну, модель как раз таки одна :)
0

#6 User is offline   melomaniac 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 182
  • Joined: 14-January 13

Posted 21 October 2013 - 12:41 AM

В общем вроде получилось, в модели сделал:

return array(
	array('feedback_name, feedback_email', 'required', 'on'=>'feedback'),
	array('spares_name', 'required', 'on'=>'spares'),


Ну и в контроллере получается:

$model=new Forms('feedback');
$model=new Forms('spares');


И все, больше ничего не трогал, вроде работает.

ORey, tuschkan, спасибо вам за помощь :)
0

#7 User is offline   melomaniac 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 182
  • Joined: 14-January 13

Posted 24 October 2013 - 02:52 PM

Всем добрый вечер. Что бы не засорять форум решил написать здесь. Продолжаю свои попытки осилить ajax валидацию.
Есть форма:
<?php $form=$this->beginWidget('CActiveForm', array(
        'id'=>'auto-form',
        'enableAjaxValidation'=>true,
        'action'=>'/forms/SendAutoForm',
        'clientOptions'=>array(
            'validateOnSubmit'=>true,
            'afterValidate'=>'js:function(form,data,hasError){
                        if(!hasError){
                                $.ajax({
                                        "type":"POST",
                                        "url":"'.CHtml::normalizeUrl(array("/forms/SendAutoForm")).'",
                                        "data":form.serialize(),
                                        "success":function(data){$("#auto-form").html("data");},
                                        
                                        });
                                }
                        }'
        ),
)); ?>

//здесь поля формы

<?php echo CHtml::submitButton(''); ?>
<?php $this->endWidget(); ?>


В контроллере:

public function actionSendAutoForm() {

		 $model=new Forms('auto-form');              
                
                if(isset($_POST['Forms']))
                { 
                  $valid=$model->validate();            
                        if($valid){
                            $auto_bodycode = $_POST['Forms']['auto_bodycode'];
			    $auto_enginecode = $_POST['Forms']['auto_enginecode'];
			    $auto_equipment = $_POST['Forms']['auto_equipment'];
			    $auto_vinframe = $_POST['Forms']['auto_vinframe'];

                            //тут еще массив из того что выше//

                            $model->content = json_encode($autoform);
                            if($model->save()){
                                echo CJSON::encode(array('status'=>'success'));
                            }
                            Yii::app()->end();
                        
                        }else{
                                // $error = CActiveForm::validate($model);
                                // if($error!='[]')
                                //     echo $error;
                                // Yii::app()->end();
                        	print_r($model->getErrors());
                            }
                        }

protected function performAjaxValidation($model)
	{
		if(isset($_POST['ajax']) && $_POST['ajax']==='feedback-form')
		{
                        $this->performAjaxValidation($model);
			Yii::app()->end();
		}

		if(isset($_POST['ajax']) && $_POST['ajax']==='spares-form')
		{
			$this->performAjaxValidation($model);
			Yii::app()->end();
		}

		if(isset($_POST['ajax']) && $_POST['ajax']==='auto-form')
		{
			$this->performAjaxValidation($model);
			Yii::app()->end();
		}
	}



И в модели:

 public $auto_bodycode;
 public $auto_enginecode;
 public $auto_equipment;
 public $auto_vinframe;

 public function rules()
	{
		// NOTE: you should only define rules for those attributes that
		// will receive user inputs.
		return array(
array('auto_bodycode, auto_enginecode, auto_equipment, auto_vinframe', 'required', 'on'=>'autoform')
);
}


Но валидация не проходит. Даже если заполнить все поля, все равно получаю в ответ:

Array
(
    [auto_bodycode] => Array
        (
            [0] => Необходимо заполнить поле «Код кузова».
        )

    [auto_enginecode] => Array
        (
            [0] => Необходимо заполнить поле «Код двигателя».
        )

    [auto_equipment] => Array
        (
            [0] => Необходимо заполнить поле «Комплектация».
        )

    [auto_vinframe] => Array
        (
            [0] => Необходимо заполнить поле «VIN или FRAME».
        )

)


Третий день сижу, не могу вкурить почему :(
0

#8 User is offline   ineersa 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 270
  • Joined: 15-April 13
  • Location:Ukraine

Posted 24 October 2013 - 04:16 PM

Бывает.
Должно быть так:
public function actionSendAutoForm() {

                $model=new Forms('auto-form');              
                if (Yii::app()->request->isAjaxRequest)
                {
                   $error = CActiveForm::validate($model);
                   if($error!='[]')
                       echo $error;
                   Yii::app()->end();
                }  
                if(isset($_POST['Forms']))
                { 
                   $model->auto_bodycode = $_POST['Forms']['auto_bodycode'];
                   $model->auto_enginecode = $_POST['Forms']['auto_enginecode'];
                   $model->auto_equipment = $_POST['Forms']['auto_equipment'];
                   $model->auto_vinframe = $_POST['Forms']['auto_vinframe'];

                            //тут еще массив из того что выше//

                   $model->content = json_encode($autoform);
                   if($model->save()){
                        echo CJSON::encode(array('status'=>'success'));
                        Yii::app()->end();
                     }
                 }


И $model->validate делайте после присвоения значений, иначе получается вы делаете валидацию пустой модели.
Еще одно,
else{
     // $error = CActiveForm::validate($model);
     // if($error!='[]')
     //     echo $error;
     // Yii::app()->end();
     print_r($model->getErrors());
     }

должно быть не тут, а вначале. Делайте проверку
if(Yii::app()->request->isAjaxRequest)
и тут делайте валидацию.

Да и еще одно, при вызове save() вызывается и validate(), так как validate() тут вам не очень нужно его можно опустить, ну или чтобы избежать двойной валидации можно использовать save(false). Иногда бывает очень полезно, особенно на больших таблицах.
Все таки нужно написать статью об аякс валидации форм, на выходных постараюсь заняться.
1

#9 User is offline   melomaniac 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 182
  • Joined: 14-January 13

Posted 24 October 2013 - 04:18 PM

View Postineersa, on 24 October 2013 - 04:16 PM, said:

Бывает.
Должно быть так:
public function actionSendAutoForm() {

                 $model=new Forms('auto-form');              
                
                if(isset($_POST['Forms']))
                { 
                  $valid=$model->validate();            
                        if($valid){
                            $model->auto_bodycode = $_POST['Forms']['auto_bodycode'];
                            $model->auto_enginecode = $_POST['Forms']['auto_enginecode'];
                            $model->auto_equipment = $_POST['Forms']['auto_equipment'];
                            $model->auto_vinframe = $_POST['Forms']['auto_vinframe'];

                            //тут еще массив из того что выше//

                            $model->content = json_encode($autoform);
                            if($model->save()){
                                echo CJSON::encode(array('status'=>'success'));
                            }
                            Yii::app()->end();
                        
                        }else{
                                // $error = CActiveForm::validate($model);
                                // if($error!='[]')
                                //     echo $error;
                                // Yii::app()->end();
                                print_r($model->getErrors());
                            }
                        }


И $model->validate делайте после присвоения значений, иначе получается вы делаете валидацию пустой модели.
Еще одно,
else{
     // $error = CActiveForm::validate($model);
     // if($error!='[]')
     //     echo $error;
     // Yii::app()->end();
     print_r($model->getErrors());
     }

должно быть не тут, а вначале. Делайте проверку
if(Yii::app()->request->isAjaxRequest)
и тут делайте валидацию.

Да и еще одно, при вызове save() вызывается и validate(), так как validate() тут вам не очень нужно его можно опустить, ну или чтобы избежать двойной валидации можно использовать save(false). Иногда бывает очень полезно, особенно на больших таблицах.
Все таки нужно написать статью об аякс валидации форм, на выходных постараюсь заняться.


ineersa, огромное вам спасибо, сейчас буду разбираться :)
0

#10 User is offline   ineersa 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 270
  • Joined: 15-April 13
  • Location:Ukraine

Posted 24 October 2013 - 04:25 PM

Я переписал ваш контроллер, так должно работать.

Не углядел

protected function performAjaxValidation($model)
        {
                if(isset($_POST['ajax']) && $_POST['ajax']==='feedback-form')
                {
                        $this->performAjaxValidation($model);
                        Yii::app()->end();
                }

                if(isset($_POST['ajax']) && $_POST['ajax']==='spares-form')
                {
                        $this->performAjaxValidation($model);
                        Yii::app()->end();
                }

                if(isset($_POST['ajax']) && $_POST['ajax']==='auto-form')
                {
                        $this->performAjaxValidation($model);
                        Yii::app()->end();
                }
        }


Вам явно нужно отдохнуть, взглянете на свежую голову, очень удивитесь.
1

#11 User is offline   melomaniac 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 182
  • Joined: 14-January 13

Posted 24 October 2013 - 04:38 PM

View Postineersa, on 24 October 2013 - 04:25 PM, said:

Я переписал ваш контроллер, так должно работать.

Не углядел

protected function performAjaxValidation($model)
        {
                if(isset($_POST['ajax']) && $_POST['ajax']==='feedback-form')
                {
                        $this->performAjaxValidation($model);
                        Yii::app()->end();
                }

                if(isset($_POST['ajax']) && $_POST['ajax']==='spares-form')
                {
                        $this->performAjaxValidation($model);
                        Yii::app()->end();
                }

                if(isset($_POST['ajax']) && $_POST['ajax']==='auto-form')
                {
                        $this->performAjaxValidation($model);
                        Yii::app()->end();
                }
        }


Вам явно нужно отдохнуть, взглянете на свежую голову, очень удивитесь.


ineersa, еще раз спасибо. Наверное вы правы, стоит отдохнуть :)
0

#12 User is offline   melomaniac 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 182
  • Joined: 14-January 13

Posted 24 October 2013 - 10:49 PM

Всем доброе утро, с обычными полями разобрался вроде, но как быть с динамическими ?

К примеру, есть такая строка формы:

<?php echo $form->textField($model,'spares_name[]', array('placeholder'=>'Название запчасти')); ?>
<?php echo $form->error($model,'spares_name'); ?>


Поля в форме можно добавлять динамически, по умолчанию оно 1, но может быть и 10, и 20. Собственно получаю массив значений в контроллере следующего вида:

$spares_name = $_POST['Forms']['spares_name'];

array(7) {
  [0]=>
  string(18) "Запчасть 1"
  [1]=>
  string(18) "Запчасть 2"
  [2]=>
  string(18) "Запчасть 3"
  [3]=>
  string(18) "Запчасть 4"
  [4]=>
  string(18) "Запчасть 5"
  [5]=>
  string(18) "Запчасть 6"
  [6]=>
  string(18) "Запчасть 7"
}


Нашел пример в доках http://www.yiiframew...1/ru/form.table, но там скорее редактирование, а у меня именно сохранение. Принцип я то вроде понял - пробежаться foreach по массиву этих самых полученных значений полей и проверить каждое, но как я не пытался пристроить следующую часть кода:

$model->content=$_POST['Forms']['spares_name'];
$valid=true;
				        foreach($model->content as $i=>$item)
				        {
				            if(isset($_POST['Forms'][$i]))
				                $item->attributes=$_POST['Forms'][$i];
				            	$valid=$item->validate() && $valid;
				        }


Получаю в ответ Fatal error: Call to a member function validate() on a non-object.

Гугл ничего не подсказал достойного, надеюсь на вашу помощь :(
0

#13 User is offline   ineersa 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 270
  • Joined: 15-April 13
  • Location:Ukraine

Posted 25 October 2013 - 02:01 AM

Все верно, $item ведь у вас не обьект, зачем его мучить)

Для такого есть 2 варианта.
1) Свой валидатор:
//модель
class MyModel extends CActiveRecord
{
    public $spares=array();
    
    public function rules()
    {
        
        return array(
            ....
            array('spares','checkSpares'),
        );
    }
    
    public function checkSpares()
    {
    //тут делаем валидацию чего нам нужно
    //ошибки пихаем как $this->addError('spares','error text');
    }
}


2й вариант, поправить rules:
class MyModel extends CActiveRecord
{
    public $spares=array();
    
    public function rules()
    {
        $rules = array(
        ......//ваши старые rules
        );
        foreach ($spares as $key=>$spare)
        {
            array_push($rules,array("spares[$key]",'required'));//тут добавляем валидации которые нам надо
        }
        return $rules;
    }


Нужно немного поправить контроллер, по сути единственное что нам нужно это:
$model->spares=$_POST['Forms']['spares_name'];
$model->validate();


И мы точно также получим ошибки валидации вдруг чего в getErrors().

Еще одно, насчет подсветки полей, вы вывели ошибку только для верхнего элемента(массива), если же вам нужна подсветка полей внутри массива с выводом ошибок, попробуйте тоже самое, только атрибуты делайте в виде spares[$i].
Тоесть для этого подходит 2й вариант. В этом варианте вью должно выглядеть как то так:

for($i = 0; $i <= 10; $i++)
<?php echo $form->textField($model,"spares_name[$i]", array('placeholder'=>'Название запчасти')); ?>
<?php echo $form->error($model,"spares_name[$i]"); ?>


Не на 100% уверен что так будет работать, но по логике вещей должно.
1

#14 User is offline   melomaniac 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 182
  • Joined: 14-January 13

Posted 25 October 2013 - 04:13 PM

View Postineersa, on 25 October 2013 - 02:01 AM, said:

Все верно, $item ведь у вас не обьект, зачем его мучить)

Для такого есть 2 варианта.
1) Свой валидатор:
//модель
class MyModel extends CActiveRecord
{
    public $spares=array();
    
    public function rules()
    {
        
        return array(
            ....
            array('spares','checkSpares'),
        );
    }
    
    public function checkSpares()
    {
    //тут делаем валидацию чего нам нужно
    //ошибки пихаем как $this->addError('spares','error text');
    }
}


2й вариант, поправить rules:
class MyModel extends CActiveRecord
{
    public $spares=array();
    
    public function rules()
    {
        $rules = array(
        ......//ваши старые rules
        );
        foreach ($spares as $key=>$spare)
        {
            array_push($rules,array("spares[$key]",'required'));//тут добавляем валидации которые нам надо
        }
        return $rules;
    }


Нужно немного поправить контроллер, по сути единственное что нам нужно это:
$model->spares=$_POST['Forms']['spares_name'];
$model->validate();


И мы точно также получим ошибки валидации вдруг чего в getErrors().

Еще одно, насчет подсветки полей, вы вывели ошибку только для верхнего элемента(массива), если же вам нужна подсветка полей внутри массива с выводом ошибок, попробуйте тоже самое, только атрибуты делайте в виде spares[$i].
Тоесть для этого подходит 2й вариант. В этом варианте вью должно выглядеть как то так:

for($i = 0; $i <= 10; $i++)
<?php echo $form->textField($model,"spares_name[$i]", array('placeholder'=>'Название запчасти')); ?>
<?php echo $form->error($model,"spares_name[$i]"); ?>


Не на 100% уверен что так будет работать, но по логике вещей должно.


Спасибо, гляну, еще нашел вариант с validateTabular, может кому пригодится:

if(Yii::app()->getRequest()->getIsAjaxRequest()) {
            if (isset($_POST['Profile'])) {
                foreach ($_POST['Profile'] as $key => $value) {
                    $profiles[] = new Profile;
                }
            }
            echo CActiveForm::validateTabular(  $profiles );
            Yii::app()->end();
}

0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users