POST variable model array issue

Hi I have spent 3 days resolving this but could not. Please help

I have view file where I have 3 text fields. These text fields are part of a model called teammember.

  • fname

  • lname

  • email

User comes in fill in values for these fields and click ‘+’ button. These values are stored in a div.

Then user enters this info again…so on and so forth. Once user is done he submits the form.

My problem is that in the POST variable only the last values are stored for teammemeber[fname],teammemeber[lname] and teammemeber[email].

I have converted those textfields to array by giving name as an array but of no use.

Please help. I am going crazy over this. I am just looking for a direction.

BR,

Vic

This is tabular input and must be treated as such.

You have your input names like: teammemeber[fname] when then should be teammemeber[0][fname],teammemeber[1][fname] etc.

Now from what you described, you clone the original input fields, but you’ll have to handle them with jQuery something like:




// this gets triggered when + is pressed

function insertFieldsInHtmlForm(){

   var uniqueID = (new Date()).getTime();

   var fields = '<input type="text" name="teammemeber['+uniqueID+'][fname]" />';

       fields+= '<input type="text" name="teammemeber['+uniqueID+'][lname]" />';

       fields+= '<input type="text" name="teammemeber['+uniqueID+'][email]" />';

   

   $("form#your-form-id").append(fields);

}



The above code will assure that you insert tabular input fields and when you save them, you will have an array like:




Array(

  

   123456789 => (  fname=>some text, lname=>other text, email=> email@address ),

   123456799 => (  fname=>new text, lname=>new again, email=>email@new)


);



Now when this form is sent you will have to loop through $_POST[teammmember], like:




if(isset($_POST['teammember'])){

   foreach($_POST['teammeber'] AS $uniqueID=>$attributesArray){

       $member=new TeamMember();

       $member->attributes=$attributesArray;

       $member->save();

   }

}



This will get you going with "creating" part, when updating, it can be done like:




if(isset($_POST['teammember'])){

   foreach($_POST['teammeber'] AS $uniqueID=>$attributesArray){

       $member=TeamMember::model()->findByPk((int)$uniqueID);

       if(empty($member))

          $member=new TeamMember();


       $member->attributes=$attributesArray;

       $member->save();

   }

}



Mainly because, when you update records, and you generate the input fields you will do it like:




if(!empty($members)){

   foreach($members AS $member){

      echo '<input type="text" name="teammember['.$member->member_id.'][fname]" />';

      echo '<input type="text" name="teammember['.$member->member_id.'][lname]" />';

      echo '<input type="text" name="teammember['.$member->member_id.'][email]" />';


   }

}



As you see, when updating records, we use the member ID to group the tabular input and when we create new records, we use a unique integer generated from javascript, namely the current time in microseconds, this assures that there will be no collision between existing fields and the new created fields.

I think i explained in details all you have to do :)

Thanks a bunch twisted1919. This looks like a great solution. I will try to implement this and I will report back.

One quick question,

when do you use chtml:activetextfield vs form->textfield?

Best Regards,

Vic

active* family is used when you have a $model to generate the input from.

In your case however, use CHtml::textField(), it’s better to stay away from the active* family when working with tabular input.

Btw, quick hint, to use CHtml to generate your jquery input fields, you will have to do it like:




function insertFieldsInHtmlForm(){

   var uniqueID = (new Date()).getTime();

   var fields = '<?php echo CHtml::textField("teammember[@][fname]");?>';

       fields+= '<?php echo CHtml::textField("teammember[@][lname]");?>';

       fields+= '<?php echo CHtml::textField("teammember[@][email]");?>';

       fields = fields.replace(/@/g,uniqueID);

   $("form#your-form-id").append(fields);

}



Basically you generate the inputs with the @ placeholder, but before you insert them into the form, @ is replaced with the unique id ;)

This is plain awesome. I am learning quite a few things here. Thanks!!

I will try and let you know. In my mind I think this is what I needed.

In all the Yii tutorials I have read, all of them have view generated from model. And for some reason I thought

that is the only way to do it. Can you please tell me briefly one case where creating view from model is not advisable and why?

Is not that it isn’t advisable, but it depends on how you design your application.

If your application uses a lot of jquery magic for user interface, then it is pretty ugly to create the tabular input from the model directly(in the traditional way) and to refresh the page each time the user decides to add another field set.

It really comes down on how you design your app and on how fancy you want to go with it.

Hi twisted1919

Thanks a lot for your help.I almost got it to work. I have few question.

First let me explain what exactly my intent is.

  • When user enters fname, lname and email and click ‘+’ button. This formation shows up in a div below.But I am also storing this information in a hidden text field(as suggested by you, with indices)that I sent when user submits the form.

  • I am having trouble ajax validating the form. I have attached pictures of how it all looks…

View




			<div>

                     <div align="center" class="row" >  

                               

              <?php $form=$this->beginWidget('CActiveForm', array(

              'id'=>'createteam-form',

              'enableAjaxValidation'=>true,

               'clientOptions'=>array('validateOnSubmit'=>true),

            )); ?>     

                      <br> 

                     <p align="center">Fields with <span class="required">*</span> are required.</p>

                   

                         <?php echo $form->labelEx($model,'teamname');//,array('class'=>'blue round label')); ?>

                         <?php echo $form->textField($model,'teamname',array('class'=>'medium input-text')); ?>

                         <?php echo $form->error($model,'teamname'); ?>

                               

          <hr><!--Team name text Field End-->


 <br>


<?php $this->endWidget(); ?>  


<ul id="newFields" align="center" style="font-color:#GFF">

 </ul>

 </div>  <!--ROW END-->

</div><!--FORM END-->

Controller


public function actionIndex()

{

			

		$model= new Teamname; 

			

			$model1= new Gametype;

			[b]

			$this->performAjaxValidation($model);[/b]

				  

			//if(isset($_POST['ajax']) && $_POST['ajax']==='createteam-form')

//				{

//						echo CActiveForm::validate($model);

//						echo CActiveForm::validate($model1);

//						Yii::app()->end();

//				}

         

			

			

		if(isset($_POST['teammember']))

		 {

		print_r($_POST['teammember']);

			foreach($_POST['teammember'] AS $uniqueID=>$attributesArray) {

  				if($_POST['teammember'] == "") {

   				 unset($array[$key]);

				}

				}

							$_newPOST['teammember'] = array_values($_POST['teammember']);

			echo count($_POST['teammember']) ;

			echo"space";

			echo count($_newPOST['teammember']) ;

			

 		 }


        	$model2=array();

			$model1 = Gametype::model()->findAll();

			$model2 = new User();

			$fname='';

			$lname='';

			$select = array(); 

			

		    

			 

			$this->render('createteam', array('model'=>$model,'model1'=>$model1, 'model2'=>$model2,  'select'=>$select,'fname'=>$fname,'lname'=>$lname));

	

	

	}


protected function performAjaxValidation($model)

	{

		if(isset($_POST['ajax']) && $_POST['ajax']==='createteam-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}

	}

	




Team name model




public function rules()

    {

        // NOTE: you should only define rules for those attributes that

        // will receive user inputs.

        return array(

            array('teamname', 'required'),

			array('teamname', 'unique'),

			array('teamname', 'length', 'max'=>45),

			

            // The following rule is used by search().

            // Please remove those attributes that should not be searched.

            array('teamnameid, teamname', 'safe', 'on'=>'search'),

        );

    }