Yii 1.1: Working with CGridView in Admin Panel

43 followers

This is a tutorial for how to add input text-Field, check-box, buttons in CGridView.

Scenario

This is CRUD pages for admin menu management. So, Menu model have following things:

  • menuId : INT
  • menuName : VARCHAR
  • sortOrder : INT (Admin may change menu order, based on that front side menu will render)
  • isActive : BOOL (only values with '1' will be shown in front side)
  • isDelete : BOOL (only values with '0' will be shown, whenever admin deletes any menu value will be changed to '1')

Demo

Below is how GRID will look like:

Screenshot

Fetch listing from model:

Let's start with model file. There is only one change, I want default listing by sortOrder field.

public function search()
{
    .....
    return new CActiveDataProvider($this, array(
    'criteria'=>$criteria,
    'sort'=>array(
        'defaultOrder'=>'sortOrder ASC',
    ),
    ));
}

Add TextField, checkbox, buttons in CGridView:

Now we will see view file.

  1. We need to add CGridView inside form so that we can save grid data after submission. We will use ajax to operate all things.

  2. We need to use CCheckBoxColumn which will generate checkbox first column as shown in image.

  3. We need some ajax button at bottom of the page using ajaxSubmitButton which will handle all events. Button names are self-explainable. Here i am going to use 4 buttons

    • To change status to 'Active'
    • To change status to 'In Active'
    • To delete multiple row.
    • To update sort order.
<?php $form=$this->beginWidget('CActiveForm', array(
    'enableAjaxValidation'=>true,
)); ?>
 
<?php 
    $this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'menu-grid',
    'dataProvider'=>$model->search(),
    'filter'=>$model,
    'columns'=>array(
        array(
            'id'=>'autoId',
            'class'=>'CCheckBoxColumn',
            'selectableRows' => '50',   
        ),
        'menuId',
        'menuName',
        array(
            'name'=>'sortOrder',
            'type'=>'raw',
            'value'=>'CHtml::textField("sortOrder[$data->menuId]",$data->sortOrder,array("style"=>"width:50px;"))',
            'htmlOptions'=>array("width"=>"50px"),
        ),
        array(
            'name'=>'isActive',
            'header'=>'Active',
            'filter'=>array('1'=>'Yes','0'=>'No'),
            'value'=>'($data->isActive=="1")?("Yes"):("No")'
        ),
        array(
            'class'=>'CButtonColumn',
        ),
    ),
)); ?>
<script>
function reloadGrid(data) {
    $.fn.yiiGridView.update('menu-grid');
}
</script>
<?php echo CHtml::ajaxSubmitButton('Filter',array('menu/ajaxupdate'), array(),array("style"=>"display:none;")); ?>
<?php echo CHtml::ajaxSubmitButton('Activate',array('menu/ajaxupdate','act'=>'doActive'), array('success'=>'reloadGrid')); ?>
<?php echo CHtml::ajaxSubmitButton('In Activate',array('menu/ajaxupdate','act'=>'doInactive'), array('success'=>'reloadGrid')); ?>
<?php echo CHtml::ajaxSubmitButton('Delete',array('menu/ajaxupdate','act'=>'doDelete'), array('success'=>'reloadGrid')); ?>
<?php echo CHtml::ajaxSubmitButton('Update sort order',array('menu/ajaxupdate','act'=>'doSortOrder'), array('success'=>'reloadGrid')); ?>
<?php $this->endWidget(); ?>

From above code you may wonder why i have taken Filter invisible button, reason is if you don't put it and type something in filter boxed and press enter it will invoke 'Active' button, as it the first submit button in form, you may also try some other options.

Save all grid data into database:

Looking into controller file.

public function actionAjaxupdate()
{
    $act = $_GET['act'];
    if($act=='doSortOrder')
    {
        $sortOrderAll = $_POST['sortOrder'];
        if(count($sortOrderAll)>0)
        {
            foreach($sortOrderAll as $menuId=>$sortOrder)
            {
                $model=$this->loadModel($menuId);
                $model->sortOrder = $sortOrder;
                $model->save();
            }
        }
    }
    else
    {           
        $autoIdAll = $_POST['autoId'];
        if(count($autoIdAll)>0)
        {
            foreach($autoIdAll as $autoId)
            {
                $model=$this->loadModel($autoId);
                if($act=='doDelete')
                    $model->isDeleted = '1';
                if($act=='doActive')
                    $model->isActive = '1';
                if($act=='doInactive')
                    $model->isActive = '0';                     
                if($model->save())
                    echo 'ok';
                else
                    throw new Exception("Sorry",500);
 
            }
        }
    }
}

Friends, hope this may help to newbies like me :)

Share your comments for any bug or issue, Also if you have any new thing in GRID which can be helpful in admin CRUD please share your thoughts.

I am using MasterAdmin class for auto set model values, you can check it HERE

Happy Coding!

Total 18 comments

#17027 report it
za_al at 2014/04/25 10:30am
beter query

Hi

Tanks for this wiki

I think,it is beter remove database query execute from foreach change this code:(to update one field such as status) secound code make only 1 request to DB,but your code make several request to db. :)

foreach($autoIdAll as $autoId)
            {
                $model=$this->loadModel($autoId);
                if($act=='doDelete')
                    $model->isDeleted = '1';
                if($act=='doActive')
                    $model->isActive = '1';
                if($act=='doInactive')
                    $model->isActive = '0';                     
                if($model->save())
                    echo 'ok';
                else
                    throw new Exception("Sorry",500);
 
            }

replace with

$autoIdAll = $_POST['autoId'];
            if (count($_POST['autoId']) > 0) {
                //change to int for security and prevent sql injection
                foreach ($_POST['autoId'] as $key) {
                    $autoIdAll[] = (int) $key;
                }
                $update = Yii::app()->db->createCommand()->update('tbl_test',   
                array('param' => $param), "id IN (" . implode(',', $autoIdAll) . ")");
            }
#17016 report it
Fatimah Al-Husain at 2014/04/24 04:50am
Thanks

Thank u very much it help me a lot ;)

#16247 report it
Mehul WTA at 2014/02/03 07:27am
Thanks

:)

#14159 report it
kiran sharma at 2013/07/23 02:28pm
@darioo

Its very kind to help others from posting/comment, and share your experience.

#14121 report it
darioo at 2013/07/21 07:02am
@kiran sharma

I as beginner didn't know that and I had trouble making it work, so it was for all other beginners

#14116 report it
kiran sharma at 2013/07/20 03:12pm
@darioo

Yes It Is. but here we shown view and function like important part only.

#14115 report it
darioo at 2013/07/20 01:38pm
You have to update accessRules() aswell

It is important to update accessRules() and give access to those actions

public function accessRules()
    {
        return array(
 
            array('allow', // allow authenticated user to perform 'create' and 'update' actions
                'actions'=>array('ajaxupdate'), // ALLOW AJAXUPDATE TO REGISTERED USERS
                'users'=>array('@'),
            ),
            array('deny',  // deny all users
                'users'=>array('*'),
            ),
        );
    }
#12737 report it
ankitv at 2013/04/09 04:20am
Nice Work

Your Admin panel is very useful for the yii beginners like me.

#11744 report it
fiela at 2013/01/31 08:01am
Thanks

How would you save your textfield if you want to use two models in the gcridview?

#11514 report it
Freeflow at 2013/01/18 03:04am
Adding a confirm box

Even if the data is not deleted from the database when you hit the delete-button, but only flagged to 'is_deleted' I think it might be helpful to add a confirm box to confirm the delete action. I did it like this:

<?php echo CHtml::ajaxSubmitButton('Delete',array('controller/action','act'=>'doDelete'), array('beforeSend'=>'function() { if(confirm("Are You Sure ...")) return true; return false; }', 'success'=>'reloadGrid')); ?>
#10885 report it
kiran sharma at 2012/11/29 10:27am
@basem

Hi basem, as you can see in tutorial - the author had specified that she use CRUD generator for generating model and crud pages... so, you just had to create crud and then follow above specified steps.

Happy Coding! :)

#10882 report it
basem at 2012/11/29 10:09am
where's action

Hi, Where's the action code that renders the first view before calling the action for ajaxUpdate! not working with me :(

#10120 report it
kiran sharma at 2012/10/05 01:57am
@vibhaJadwani

YesItIs, the better way to use in system...

#10119 report it
vibhaJadwani at 2012/10/05 01:48am
@Freeflow

e.g. you have user database for a big applications. There are lots of data associated with that user_id, Now when admin delete that user using code $model->delete(); then user records will permanently deleted from database. And you loose important data from database, so by setting flag isDeleted=1, you still have all data of that user in database. In front side if user have isDeleted=0 then only he can login.

#10108 report it
kiran sharma at 2012/10/04 12:26pm
@Freeflow

@Freeflow,

isDeleted is database field which is set to '1' on doDelete action. so that db field is set to '1' by,

$model->isDeleted = '1';

and then model is saved by,

$model->save()
#10102 report it
Freeflow at 2012/10/04 09:08am
One question

First of all, thanx for this nice tutorial, but I have one question:

what is the meaning of

$model->isDeleted = '1';

It is clear for'isActive', but for deleting, shouldn't there be something like

$model->delete();
#9311 report it
vibhaJadwani at 2012/08/03 01:01am
Thanks

Welcome @vothanhy.

#9234 report it
vothanhy at 2012/07/30 09:22pm
Thanks

Just copy and run well. Save my time. Thanks a lot.

Leave a comment

Please to leave your comment.

Write new article