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 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:
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.