Yii 1.1: Update CGridview row separately using ajax request

7 followers

There are cases you want to update a record on CGridview directly

In this wiki I will show how to do that

In your view file:

$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider' => $dataProvider,
    'id' => 'grid-view-id',
    'columns' => array(
        array(
            'header' => 'attribute1',
            'value' => 'CHtml::textField("TheModel[attribute1]",$data->attribute1)',
            'type' => 'raw',
        ),
        array(
            'header' => 'attribute2',
            'value' => 'CHtml::textField("TheModel[attribute2]",$data->attribute2)',
            'type' => 'raw',
        ),
        array(
            'class' => 'CButtonColumn',
            'template' => '{update}{view}{delete}',
            'buttons' => array(
                'update' => array(
                    'options' => array('class' => 'save-ajax-button'),
                    'url' => 'Yii::app()->createUrl("yourController/saveModel", array("id"=>$data->id))',
                ),
                'view',
                'delete',
            ),
        ),
    ),
));

Also in the same view file or in any way you have to load this script

<script>
    $('#grid-view-id a.save-ajax-button').live('click', function(e)
    {
        var row = $(this).parent().parent();
 
        var data = $('input', row).serializeObject();
 
        $.ajax({
            type: 'POST',
            data: data,
            url: jQuery(this).attr('href'),
            success: function(data, textStatus, jqXHR) {
                console.log(data);
                console.log(textStatus);
                console.log(jqXHR);
            },
            error: function(textStatus, errorThrown) {
                console.log(textStatus);
                console.log(errorThrown);
            }
        });
        return false;
    });
 
 
    $.fn.serializeObject = function() {
        var o = {};
        var a = this.serializeArray();
        $.each(a, function() {
            if (o[this.name]) {
                if (!o[this.name].push) {
                    o[this.name] = [o[this.name]];
                }
                o[this.name].push(this.value || '');
            } else {
                o[this.name] = this.value || '';
            }
        });
        return o;
    };
</script>

Now in your controller "yourController" in action "saveModel"

public function actionSaveModel($id){
        //save the data as you did in the properly action. For example
        if ($_POST['TheModel']) {
            $model = new TheModel();
            $model->attributes = $_POST['TheModel'];
            $model->save();
         }
    }

Thats it!

Total 9 comments

#19478 report it
Roberto Tambunan at 2015/07/21 11:39pm
Thank you

Hi Kostas,

There's no error now. But, I can't get any value from $_POST['Rptk'].

Here is my view code

<?php
/* @var $this RptkController */
/* @var $model Rptk */
 
$this->breadcrumbs=array(
    'Rptks'=>array('index'),
    'Manage',
);
 
$this->menu=array(
    array('label'=>'List Rptk', 'url'=>array('index')),
    array('label'=>'Create Rptk', 'url'=>array('create')),
);
 
Yii::app()->clientScript->registerScript('search', "
$('.search-button').click(function(){
    $('.search-form').toggle();
    return false;
});
$('.search-form form').submit(function(){
    $('#rptk-grid').yiiGridView('update', {
        data: $(this).serialize()
    });
    return false;
});
");
?>
 
 
<script>
    $('#grid-view-id a.save-ajax-button').live('click', function(e)
    {
        var row = $(this).parent().parent();
 
        var data = $('input', row).serializeObject();
 
        $.ajax({
            type: 'POST',
            data: data,
            url: jQuery(this).attr('href'),
            success: function(data, textStatus, jqXHR) {
                console.log(data);
                console.log(textStatus);
                console.log(jqXHR);
            },
            error: function(textStatus, errorThrown) {
                console.log(textStatus);
                console.log(errorThrown);
            }
        });
        return false;
    });
 
 
    $.fn.serializeObject = function() {
        var o = {};
        var a = this.serializeArray();
        $.each(a, function() {
            if (o[this.name]) {
                if (!o[this.name].push) {
                    o[this.name] = [o[this.name]];
                }
                o[this.name].push(this.value || '');
            } else {
                o[this.name] = this.value || '';
            }
        });
        return o;
    };
</script>
 
 
 
<h1>Manage Rptks</h1>
 
<p>
You may optionally enter a comparison operator (<b>&lt;</b>, <b>&lt;=</b>, <b>&gt;</b>, <b>&gt;=</b>, <b>&lt;&gt;</b>
or <b>=</b>) at the beginning of each of your search values to specify how the comparison should be done.
</p>
 
<?php echo CHtml::link('Advanced Search','#',array('class'=>'search-button')); ?>
<div class="search-form" style="display:none">
<?php $this->renderPartial('_search',array(
    'model'=>$model,
)); ?>
</div><!-- search-form -->
 
<?php $this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'rptk-grid',
    'dataProvider'=>$model->search(),
    'filter'=>$model,
     'pager'=>array(
            'class'=>'CLinkPager',
            'firstPageLabel'=>'Pertama',
                'lastPageLabel'=>'Terakhir',
            'nextPageLabel'=>'Selanjutnya',
            'prevPageLabel'=>'Sebelumnya',
            'header'=>'',
 
        ),
    'columns'=>array(
    //  'id',
    //  'AC_No',
        'NIP',
        'Nama',
        array(
            'name'=>'Tanggal',
            'filter'=>false, // Set the filter to false when date range searching
        ),
        'Jadwal_Kerja',
 
        'Jam_Masuk',
        'Jam_Pulang',
        'Scan_Masuk',
        'Scan_Pulang',
        array(
            'header' => 'Absen',
            'value' => 'CHtml::textField("Rptk[Absen]",$data->Absen)', // this is how I make the textfield
            'type' => 'raw',
        ),
        array(
            'header' => 'Keterangan',
            'value' => 'CHtml::textField("Rptk[Keterangan]",$data->Keterangan)', // this is how I make the textfield
            'type' => 'raw',
        ),
 
        /*
        'Terlambat',
        'selisih_jam_pulang',
        'Konversi_TL',
        'Pot_TL',
        'Pulang_Cepat',
        'Konversi_PC',
        'Pot_PC',
        'Absen',
        'Keterangan',
        'Pot_Ket',
        'Total_Pot_Harian',
        'Total_Pot_Bulanan',
        'Work_Time',
        'Departmen',
        'F24',
        */
        /*array(
            'class'=>'CButtonColumn',
        ),*/
     array(
            'class' => 'CButtonColumn',
            'template' => '{update}{view}{delete}',
            'buttons' => array(
                'update' => array(
                    'options' => array('class' => 'save-ajax-button'),
                    'url' => 'Yii::app()->createUrl("Rptk/saveModel", array("id"=>$data->id))',
                ),
                'view',
                'delete',
            ),
        ),
    ),
)); 
?>
<br/>
<?php echo CHtml::link('Export This',array('Rptk/excel')); ?>

And here is my Controller

public function actionSaveModel($id){
        //save the data as you did in the properly action. For example
        if (isset($_POST['Rptk'])) {
            $model = new Rptk();
            $model->attributes = $_POST['Rptk'];
            $valid = $model->validate();
 
            if($valid){
              $model->save();
            }
         }
    }
#19463 report it
Kostas Apazidis (KonApaz) at 2015/07/15 02:08am
Re: #19462

Hi Roberto

Replace the $_POST['Rptk'] with isset($_POST['Rptk']) In the first time when no post request exist you have to check it.

also comment the //var_dump($Rptk['Absen']); die();

#19462 report it
Roberto Tambunan at 2015/07/14 11:54pm
error

Undefined variable: Rptk

*/
219     protected function performAjaxValidation($model)
220     {
221         if(isset($_POST['ajax']) && $_POST['ajax']==='rptk-form')
222         {
223             echo CActiveForm::validate($model);
224             Yii::app()->end();
225         }
226     }
227 
228     public function actionSaveModel($id){
229         //save the data as you did in the properly action. For example
230         var_dump($Rptk['Absen']); die();
231         if ($_POST['Rptk']) {
232             $model = new Rptk();
233             $model->attributes = $_POST['Rptk'];
234             $valid = $model->validate();
235  
236             if($valid){
237                $model->save();
238             }
239          }
240     }
241 }
#17679 report it
Rohit Suthar at 2014/07/14 05:11am
RE: #17678

thanks for your valuable response!!

#17678 report it
Kostas Apazidis (KonApaz) at 2014/07/14 04:33am
RE: #17676

Hi Rohit,

$model->save(); or $model->save(true);

is equivalent of

$valid = $model->validate();
 
if($valid){
   $model->save();
}

$model->save(false); save the model without validation. so in our case is better to use any mentioned code except $model->save(false);

#17676 report it
Rohit Suthar at 2014/07/14 03:25am
Coooool

It's really nice script but can we use validation before save like this -

$valid = $model->validate();
 
if($valid){
   $model->save();
}

or

$model->save(false);

which one is batter???

#17453 report it
Daniel Galvan at 2014/06/13 04:05pm
Excelent Wiki!

Thank you very much for sharing.

#17148 report it
Kostas Apazidis (KonApaz) at 2014/05/07 08:57am
Re: #17143

save mothod runs the validators by default

http://www.yiiframework.com/doc/api/1.1/CActiveRecord#save-detail

So, if you don't use save method like that $model->save(false); you shouldn't worry about it :)

#17143 report it
Stageline at 2014/05/07 07:32am
Security

Don't forget validate before save!

Leave a comment

Please to leave your comment.

Write new article