Tabular Input - Create And Update

Hi all,

Following the Yii guide for tabular updates. What the guide has you do is basically fetch all your models, render them on the form, and then in the $_POST result see if the POST data is set for that model Id. If so, assign, and save.

Everything works great - form validation, updating, etc.

Now… I am wanting to add the ability to add a new record to the list. The method suggested in the Guide does not work for this - instead of iterating through the array of models retrieved via getItemsToUpdate() I need to iterate through the $_POST array… the problem is when I do this I do not get any errors displayed on the form from validation. I can retrieve them from $model->getErrors().

I think it is because the model instances passed to the form are not the same as the ones created in the controller when dealing with the $_POST array. Does anyone have insight on how to manage a combined create/update tabular form?

I use the MultiModelForm extension, and it works well. Check it out…

I looked into it, I don’t like how it clones fields. I prefer to use an ajax-based cloning because it enables you to use widgets in your cloned fields without JS workarounds that relcopy uses. I use this extension/widget for my tabular input handling:

http://www.eha.ee/labs/yiiplay/index.php/en/site/extension?view=tabular

The problem is this site does not show a working implementation of controller code to setup existing models and handle saving/ display of errors. So after a little hacking here is what I came up with - tabular input with serverside validation that works correctly:


	

	public function actionIndex()

	{

		$models=array();

		

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

		{	

			$valid=true;

			foreach($_POST['Hood'] as $i=>$hood)

			{

				if(empty($hood['id'])) //id hiddenfield is empty, so new record

				{

					$model=new Hood;

					$model->attributes=$hood;

					$model->clientId=1;

					if(!$model->validate())

						$valid=false;

					$models[]=$model;					

				}

				else //id is set, so its an existing record

				{

					$model=Hood::model()->findByPk($hood['id']); //$i is the index == primary key

					if($model)

					{

						$model->attributes=$hood;

						$model->clientId=1;

						if(!$model->validate())

							$valid=false;

						$models[]=$model;

					}						

				}

			}

			if($valid && !empty($models))

			{

				//save em

				foreach($models as $m)

				{

					$m->save(false); //already validated, don't repeat yourself

				}

			}

		}

if(empty($models)) //if nothing added to models array, create from db

			$models=Hood::model()->findAll(array('index'=>'id'));

		

		$this->render('tabular', array(

			'hoods'=>$models,

		));

	}



A few clarifying points:

  • For records that you want to update, index them by PK and not by 0-based index which is default. See my findAll() method for an example.

  • Put a hiddenfield in your view with the id (pk) along with each record

  • The workflow for dealing with related models is very similar

I admit that MMF gave me trouble using simple Ajax calls (not even widgets) but I managed to get it working for my previous needs. I will take a look at the widget you refer to and if I come up with any suggestions I’ll let you know, as it may be useful to me in the future.

Thanks,