Multimodel Forms Y Cjuitabs

Saludos a todos.

Soy novatillo en Yii y estoy haciendo un proyecto para ir avanzando.

Estoy intentando crear un form con tres modelos, y que haga un renderpartial con cada uno de los _form de los modelos (factura, cliente, productoXXX). Aún es un prototipo, por éso factura es model ahora, y en un futuro próximo será model_factura.

Lo he realizado con la vista create y con un renderPartial:


echo $this->renderPartial('_form', array('model'=>$model, 'model_cliente'=>$model_cliente, 'model_producto001'=>$model_producto001,));

Accedo al _form de factura completo en el view create y le voy insertando los campos de cada modelo:




	<?php

$this->widget('zii.widgets.jui.CJuiDatePicker', array(

    'name'=>'Factura[fecha_venta]',

   // 'header'=>'fecha_venta',

    // additional javascript options for the date picker plugin

    'options'=>array(

        'showAnim'=>'fold',

        'dateFormat'=>'dd-mm-yy',

    ),

    'htmlOptions'=>array(

        'style'=>'height:20px;width:80px;'

    ),

));	

?>

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

		<?php echo $form->labelEx($model_cliente,'nombre'); ?>

		<?php echo $form->textField($model_cliente,'nombre'); ?>

		<?php echo $form->error($model_cliente,'nombre'); ?>


    $products = Producto::model()->findAll('area = :area', array(':area' => $_GET['id']));


      echo "Producto: ".CHtml::activeDropDownList($model, 'producto_id', CHtml::listData($products, 'producto_id', 'nombre'));


// etc...



Funciona bien, valida y graba en la base de datos.

Pero me gustaría integrarlo con un CJuiTabs. No es imprescindible, pero sí sería deseable… Sobre todo porque cada factura puede tener un sólo producto, y éste ser heterogéneo (desde bebidas alcohólicas hasta paseos en helicóptero, de ahí lo de ProductoXXX)

En el _form de factura tendría sus campos, y llamaría a un partial (o un método similar) para el _form de cliente y el de productoXXX.

En mi Factura controller, en el actionCreate tengo:




		$model=new Factura;

		$model_cliente=new Cliente;

		$model_producto001=new Producto001;

		if(isset($_POST['Factura'], $_POST['Cliente'], $_POST['Producto001']))

		{

// ajax validate & save

                }

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

		'model'=>$model,

		'model_cliente'=>$model_cliente,

		'model_producto001'=>$model_producto001,

	));

Pero en el create de factura sólo me funciona bien así:


$this->widget('zii.widgets.jui.CJuiTabs',array(

    'tabs'=>array(

        'type1'=>$this->renderPartial('_form',array('model' => $model, 'model_cliente'=>$model_cliente, 'model_producto001'=>$model_producto001, ), true ),

        'StaticTab 2'=>array('content'=>'Content for tab 2', 'id'=>'tab2'),

        // 'eltres'=>$this->renderPartial('_form', array('model_cliente'=>$model_cliente, ), $this),

        // panel 3 contains the content rendered by a partial view

       // 'AjaxTab'=>array('ajax'=>$ajaxUrl),

    ),

    // additional javascript options for the tabs plugin

    'options'=>array(

        'collapsible'=>true,

    ),

));

No soy capaz de meter en cada tab su partial y que no me genere errores.

Me imagino que el problema está en la declaración de modelos dentro del actionCreate o de cómo paso los modelos al render(‘create’=> para que luego me funcionen los partial independientemente de si están ‘dentro’ del form Factura o no.

No sé si me he explicado bien.

¿Alguien me puede orienter en la dirección correcta?

Gracias anticipadas.

Hola de nuevo.

He solucionado el renderpartial, con los tres modelos. El problema lo tenía en varios sitios.

Básicamente, no llamaba bien a los _form de los modelos y validaba los tres como al principio, en el _form de factura.

Los pongo independientes, como deberían, y funciona la ‘vista’ del form completo con los tabs.

Cambié en factura create.php la definición de los tabs:


        $this->widget('zii.widgets.jui.CJuiTabs',array(

    'tabs'=>array(

'cliente'=>$this->renderPartial('application.views.cliente._form',array('model' => $model_cliente),true),

        'producto001'=>$this->renderPartial('application.views.producto._form',array('model' => $model_producto001),true),

        'factura'=>$this->renderPartial('_form',array('model' => $model ), true),    ),

    // additional javascript options for the tabs plugin

    'options'=>array(

        'collapsible'=>true,

    ),

)); 

Pero me crea tres formularios independientes, con sus tres submit.

¿Cómo puedo agrupar los tres forms independientes en un sólo form sin que interfiera con el begin form de cada _form?


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

	'id'=>'cliente-form',

	'enableAjaxValidation'=>false,

)); ?>

Gracias.

Probaste de sacar los forms de cada archivo y agruparlos en 1 solo? Sino también podés sacar el Begin Form y el End Form de cada uno y podés poner solo uno que englove los 3 renderPartial.

Saludos

Hola Sebas.

Efectivamente, ahora ya tengo un ‘megaform’ con los tres modelos, y es la solución más eficaz que veo. Pero soy novatillo y no estoy seguro de que sea lo mejor.

Por widgets no consigo pasarle el modelo bien.

A partir de ahí he metido cada form de modelo en el sistema de tabs ‘a mano’, que tampoco veo mucho problema.

Una vez hecho esto, el ‘inconveniente’ que tengo es que no puedo ver los errores de cada modelo independientes.

Intentaré explicarme mejor.

Tengo los tres modelos en un megaform, al que llamo desde el controller->actionCreate,


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

		'model'=>$model,	

 		'model_cliente'=>$model_cliente,

		'model_recibo'=>$model_recibo,

	));

En create.php:


echo $this->renderPartial('_megaform', array('model'=>$model, 'model_cliente'=>$model_cliente, 'model_recibo'=>$model_recibo), true);



Y en el _megaform:


<?php echo $form->errorSummary($model, 'Factura HEADER ERROR', 'FOOTER ERROR'); ?>

<?php echo $form->errorSummary($model_cliente, 'Cliente HEADER ERROR', 'FOOTER ERROR'); ?>

<?php echo $form->errorSummary($model_recibo, 'Recibo HEADER ERROR', 'FOOTER ERROR'); ?>

// aquí el sistema de tabs con los miniforms de cada modelo

// etc...

En el controller de factura tengo las validaciones:


		$this->performAjaxValidation($model, $model_cliente, $model_recibo);


		if(isset($_POST['Factura'], $_POST['Cliente'], $_POST['Recibo']))

		{

			$model->attributes=$_POST['Factura'];

			$model_cliente->attributes=$_POST['Cliente'];

			$model_recibo->attributes=$_POST['Recibo'];


// validate ALL $model, $model_cliente and $model_recibo

			$valid = $model->validate();

			$valid = $model_cliente->validate() && $valid;

			$valid = $model_recibo->validate() && $valid;

// etc...

A partir de ahí, si no tiene errores se salva bien.

Si tiene un error lo muestra, pero no independientemente de cada modelo. Esto es, dentro del primer “errorSummary($model, 'Factura Header…)”. No salen los demás headers

Si elimino esa línea los errores se muestran con el header de la segunda línea, el del cliente. O el de recibo si sólo está ése.

Si no tiene errores de factura, pero sí de cliente o recibo, se muestran todos dentro de la primera línea que encuentre, o la que exista.

Intento sacar tres cajas con errores independientes. Y creo que al principio lo conseguí (pero no salvé…).

Los de factura en la caja de factura, los de cliente en su caja, …

Sí he verificado que llamo al begin form y end form en _megaform y el fuente aparece bien formado el form, y que no hay <form internos, y si no hay errores se guarda todo correctamente:


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

	'id'=>'factura-form',

	'enableAjaxValidation'=>true,

	'enableClientValidation'=>true,

    'clientOptions' => array(

		'validateOnSubmit'=>true,

		'validateOnChange'=>true,

 		'validateOnType'=>false,

          ),

)); ?>


...


<div class="form-actions">

    <?php $this->widget('bootstrap.widgets.TbButton', array('buttonType'=>'submit', 'type'=>'primary', 'label'=>'Submit')); ?>

    <?php $this->widget('bootstrap.widgets.TbButton', array('buttonType'=>'reset', 'label'=>'Reset')); ?>

</div>

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




Gracias por la respuesta.