Ciao a tutti, ho deciso di raccontarvi la mia prima esperienza con questo MVC ed un tentativo (abbastanza) riuscito di gestire le operazioni di CRUD dalla CGridView tramite un CJuiDialog.
La mia tecnica parte dalla generazione del codice con GII e sembra lasciare intatta la validazione ajax delle form ed è abbastanza semplice da implementare. Ho cercato di rendere, dove possibile, il codice generico.
Attendo vostri commenti. Sarei felice se collabboraste al perfezionamento di questo codice al fine di trasformare questo mini tutorial in una pagina del wiki.
Bruno
Let’s go. Dopo aver generato il codice con GII, assumo che il modello si chiami MyModel
Nel controller MyModelController:
Esempio di azione per la creazione di un nuovo elemento da modello:
public function actionCreate()
{
$model=new MyModel;
$this->performAjaxValidation($model);
if(isset($_POST['MyModel']))
{
$model->attributes=$_POST['AdsList'];
$result = $model->save();
if (Yii::app()->request->isAjaxRequest)
{
echo $result ? "ok" : "ko";
exit();
}
else
{
$this->redirect(array('view','id'=>$model->id));
}
}
if (Yii::app()->request->isAjaxRequest)
{
$this->renderPartial('_create_dialog', array('model'=>$model),false,false);
}
else
{
$this->render('create',array('model'=>$model));
}
}
Vista _create_dialog da creare all’interno della cartella delle viste
relative al modello in oggetto (es. views/MyModel/_create_dialog.php)
Esempio di azione per la creazione di un nuovo elemento da modello:
<?php
// Questa riga la devo a psikocrisis!!!
Yii::app()->clientScript->scriptMap=array(
//scripts that you don't need inside this view
'jquery.js'=>false,
);
$this->beginWidget('zii.widgets.jui.CJuiDialog',array(
'id'=>'createDialog',
'options'=>array(
'title'=>Yii::t('app','Create New Record'),
'autoOpen'=>true, // naturalmente apriamo il dialog dopo il rendering
'modal'=>'true', // finestra di modifica modale
'width'=>'640', // qui possiamo scegliere le dimensioni che ci gustano
'height'=>'500', // qui possiamo scegliere le dimensioni che ci gustano
'buttons'=>array(
Yii::t('app','Save')=>'js:function() { submitForm(this) }',
Yii::t('app','Close')=>'js:function() { $(this).dialog("close"); }'
), // Notare i bottoni di SAVE e CLOSE <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/smile.gif' class='bbc_emoticon' alt=':)' />:)<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/smile.gif' class='bbc_emoticon' alt=':)' />
'close'=>'js:function() { $(this).html(""); updateGrid() }' // sul salva aggiorna la grid
),
));
// questo renderizza la nostra classica form <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/smile.gif' class='bbc_emoticon' alt=':)' />
echo $this->renderPartial('_form', array('model'=>$model),false,true);
$this->endWidget('zii.widgets.jui.CJuiDialog');
?>
Nel file della vista principale, dove viene renderizzata normalmente la
CGridView, ossia admin.php, abbiamo una serie di accorgimenti semplicissimi:
A ) Dove viene registrato il javascript della ricerca:
Yii::app()->clientScript->registerScript('refreshbtn', "
$('#refresh-button').click(function(){
$.fn.yiiGridView.update('ads-list-grid');
});
");
[u] B ) A fianco del link che apre la ricerca avanzata metto un altro link per il
refresh della grid che richiama lo script al punto A)[/u]
<?php echo CHtml::link(Yii::t('app','Refresh'),'#',array('id'=>'refresh-button')); ?>
C ) Subito dopo questo link, ne aggiungo un altro per la creazione di un record:
<?php
echo CHtml::ajaxLink(Yii::t('app','Add New'),
Yii::app()->createUrl("MyModel/create"),
array(
'type'=>'POST',
'url'=>'js:$(this).attr("href")',
'update'=>'#updatediv', // il target della chiamata ajax è un div che mettiamo a fine pagina
'cache'=>'false'
),
array('id'=>'new-button'));
?>
D ) Modifica alla riga di codice predefinita che crea la CGridView:
$grid = $this->widget('zii.widgets.grid.CGridView', array(
questa modifica serve per poter avere in $grid il widget e poter utilizzare del
codice generico nelle fasi successive:
[u] E ) A fine pagina, inserire il seguente codice che serve per forzare l’update della
grid e per inserire nella pagina il DIV target delle chiamate per la creazione del
dialog:[/u]
<?php
Yii::app()->clientScript->registerScript('updatedivscript','
function updateGrid() {
$.fn.yiiGridView.update("' . $grid->id . '");
}',CClientScript::POS_END);
?>
<div id="updatediv"></div>
Modifiche al file della vista _form presente in views/MyModel/_form.php
A ) In testa alla form:
<?php
$form=$this->beginWidget('CActiveForm', array(
'id'=>'mymodel-list-form',
'enableAjaxValidation' => true,
'clientOptions'=>array(
'validateOnSubmit'=>false,
'validateOnChange'=>true,
),
));
// Script per gestire l'invio dei dati della form al controller in modalità
// ajax ed eventualmente chiudere il form dopo il salvataggio o mostrare gli
// errori di validazione.
Yii::app()->clientScript->registerScript($form->id . "-submit",'
function submitForm(dlg) {' .
CHtml::ajax(array(
'type'=>'POST',
'cache'=>'false',
'data'=>'js:$("form#'. $form->id . '").serialize()',
'url'=>Yii::app()->request->requestUri,
'success'=>'js:function(data) { if (data=="ok") { $(dlg).dialog("close"); return false; } else { alert("Error: " + data);} }'
)
).'
}');
B ) Eliminare la row con i bottoni di salvataggio generati da GII
Per gestire la modifica, la tecnica è uguale. Basta modificare - in modo simile alla create - l’azione di update ed implementare le relative viste in modo affine a quanto visto sopra.
Magari è utile modificare il bottone della modifica nella CGridView, modificando il codice di default con questo snippet:
$grid = $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'mymodel-list-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
[...]
),
array
(
'class'=>'CButtonColumn',
'template' => '{update} {delete}',
'buttons'=>array(
'update'=>array (
'url'=> 'Yii::app()->createUrl("myModel/update", array("id" => $data->id))',
'options'=>array (
'ajax'=>array(
'type'=>'POST',
'url'=>'js:$(this).attr("href")',
'update'=>'#updatediv',
'cache'=>'false'
),
),
),
),
),
);
Questo è quanto. Attendo speranzoso vostre idee / suggerimenti…