Ajax Delete Call In Cbuttoncolumn On A Grid Of Data

My page allows user to select a Person, and that person’s details & related data will display. One of the pieces of related data is the families that person belongs to.

It is displayed in a CGridView, where the information for each family that person belongs to is shown. I am wanting to use a CButtonColumn to be able to allow the user to remove someone from a family within the GridView itself.

I am wanting this to be done via an AJAX call, so the user won’t have the page refreshed on a delete call. I am aware that in the ‘buttons’ attribute that you can set, there is a ‘click’ attribute for each button, that is a JS function that is run when a button is clicked.

I am fine with the AJAX call itself, but I am struggling trying to figure out how to extract the data out of the GridView, specifically for the line that the user wishes to delete. Because the link table uses a concatenated key combined of both the unique ID of the family, and the unique ID of the person, I am going to need both pieces of data. The unique ID of the person is not stored anywhere within the CGridView itself, since it just displays family data that was pre-calculated in the model. So I am going to need to get the JS function to also extract the unique ID from one of the PHP variables on the display page ($Details->personID).

Any help is appreciated. Here is the widget I’m using for this:




$this->widget('bootstrap.widgets.TbGridView', array(

                        'id' => "famGrid",

                        'type' => 'striped bordered',

                        'dataProvider' => $relatedData['families'],

                        'selectableRows' => false,

                        'columns' => array(

                            array(

                                'name' => 'Family Name',

                                'value' => '$data->Name'

                            ),

                            array(

                                'name' => 'Description',

                                'value' => '$data->Description'

                            ),

                            array(

                                'htmlOptions' => array('nowrap'=>'nowrap'),

                                'class'=>'bootstrap.widgets.TbButtonColumn',

                                'afterDelete' => '$(function(){$.fn.yiiGridView.update("famGrid");})',

                                'buttons' => array(

                                    'view' => array(

                                        'visible' => function($row,$data){false;},

                                    ),

                                    'update' => array(

                                        'visible' => function($data,$row){false;},

                                    ),

                                    'delete' => array(

                                        'click' => '$(function(){' // this is the problematic bit

                                        . 'var jqxhr = $.ajax({'   // need family id and person id

                                        . 'type: "POST", '

                                        . 'url: "person/DelFam", '

                                        . 'data: ""})'

                                        . '});'

                                    )

                                )

                            )

                        )

                    ));



You’re overcomplicating it a bit. The delete request is automatically processed using AJAX. Just encode all of the information that you need in the URL:




'buttons'=>array(

    ...

    'delete'=>array(

        'url'=>function($data){

            return Yii::app()->createUrl('/person/delFam',

                    array('id'=>$data->id) /* <- customise that */

            );

        },

    ),

),



You also don’t need the afterDelete attribute, as Yii automatically refreshes the grid after a delete request.

Your action will look something like this:




public function actionDelFam($id)

{

    // Only accept POST requests over AJAX

    if (!Yii::app()->request->isPostRequest || !Yii::app()->request->isAjaxRequest)

        throw new CHttpException(400, 'Invalid request.');


    $fam = /* fetch the record */;


    if ($fam)

        $fam->delete();

}



Nothing else is required. The 200 response that Yii automatically sends will cause the JS to treat the request as successful and refresh the grid.

Thanks for your reply, you’ve really helped me understand this better. I have just one problem. As I said in my OP, in order to find the right record in the link table, I also need the unique ID of the person in question. I have a variable passed through to the view file from the controller called $Details, which is a model instance of the specific person. I modified your callback to try to include $Details->personID, which is the variable containing the unique ID of that person. See here:




function($data){

           return Yii::app()->createUrl('/person/delFam',

           array('Family'=>$data->familyID, 'Person'=>$Details->personID)

           );

      },



However, I got an error saying that $Details is not initialised. I imagine this is the case because we are in the scope of the CButtonColumn view, separate from the main view file. Is there anyway around this?

Use the "use" keyword to bring it into scope in the function:




function ($data) use ($Details){

    ...

},



Thanks for your help Keith. Very helpful!