Foreign Key Constraints

I’ve tried that also, doesn’t make any difference.

Incidently, if I output just ‘data’ in my afterAjaxUpdate function, I get a load of XHTML markup beginning with the <!DOCTYPE> tag…

I have managed to this by modifying the CButtonColumn.php file and changing the jQuery delete function as follows:


function() {

	function setFlash(message) {

		$('#flash-message').html(message);

		$('#flash-message').fadeIn().animate({opacity: 1.0}, 3000);

		$('#flash-message').fadeOut('slow');

	}

	$confirmation

	$.fn.yiiGridView.update('{$this->grid->id}', {

		type:'POST',

		dataType:'json',

		url:$(this).attr('href'),$csrf

		success:function(data) {

			setFlash(data.message);

			$.fn.yiiGridView.update('{$this->grid->id}');

		}

	});

	return false;

}

And I don’t need anything in afterAjaxValidate function in CGridView for this to work. But this isn’t my preferred method of doing this, can it be done without having to modify the core file or creating a custom delete function? I.e. in the afterAjaxValidate function?

That is very weird GSTAR as when I do JSON::encode it does returns and through its function I get the variable.property correctly.

In your success function, did you make sure that a ‘data’ parameter is actually used?

function success(data){ alert(data.message); }

Yeah, I tried it like this:


'afterAjaxUpdate'=>"function setFlash(id, data) {

	$('.flash-error').html(data.message);

	alert(data.message);

}",

alert(data.message) outputs ‘undefined’

alert(data) outputs a load of XHTML markup.

GSTAR, if your response is {“message”:“The User could not be deleted.”} and your dataType is set to ‘json’, the only place to look for any problems is your success ajax function.

Please check if you have a success: function(data) {} declaration. Without data as parameter, you wont be able to reach data.message.

When you put dataType: ‘json’, you say to jquery that the expected response will be of JSON data type and it will automatically evaluate that for you.

The load if XHTML markup is the CGridView code, that is returned by the default response of CGridView.

That’s why I was not sure it was actually possible to do like that, because the CGridView has already his standard response (the updated grid itself) and I don’t know if it is possible to change it.

I advice a rouge solution, to output in the CGridView the js code for se the flash message:




<script type="text/javascript">

$('.flash-error').html(data.message);

</script>



You can echo this code, for example, in the filter option of some column, or in a dataColumn (but only once), in a word: wherever, the only important stuff is that it has to be INSIDE the CGRidView.

You won’t need to set afterAjaxUpdate, nothing. CgridView will do his job, and you will simply put inside the grid your js code.

Simple, dirty and effective.

Don’t fight against Zii widget, they will always win. Let them do their standard job, and you enjoy the results.

Hey GSTAR,

I did not find an elegant solution for this problem either. What I do is to hide the delete button when the row has related records. This is a real world scenario with counties and addresses.

In County model:




public function relations()

{

    return array(

        'city' => array(self::BELONGS_TO, 'City', 'cityId'),

        'addresses' => array(self::HAS_MANY, 'Address', 'countyId'),

        'addressCount' => array(self::STAT, 'Address', 'countyId'),

    );

}



In the view:




<?php $this->widget('zii.widgets.grid.CGridView', array(

    'dataProvider' => $county->search(),

    'filter' => $county,

    'columns' => array(

        'name',

        array(

            'name' => 'cityId',

            'filter' => CHtml::listData($cities, 'id', 'name'),

            'value' => '$data->city->name',

        ),

        array(

            'class' => 'CButtonColumn',

            'template' => '{update}{delete}',

            'buttons' => array(

                'delete' => array(

                    'visible' => '$data->addressCount === 0',

                )

            ),

        ),

    ),

)); ?>



Thansk for the suggestion zaccaria, however that does not work - it says "data is not defined" (JS error)

$(’.flash-error’).html(data.message);

Antonio - what I’m saying is I want to retain the original delete function that is in CButtonColumn.php and use ‘afterAjaxUpdate’ or something similar in my CGridView to generate the AJAX flash message.

You can do like this:

Controller:




try{

                $this->loadModel()->delete();

                Yii::app()->user->setFlash('success', "ok");

            }

            catch (CDbException $e){

                Yii::app()->user->setFlash('error', "error");

		$this->redirect(array('admin'));

                exit;

            }



in the view:




<?php if(Yii::app()->user->hasFlash('success')): ?>

    <div class="flash-success"><?php echo Yii::app()->user->getFlash('success'); ?></div>

<?php elseif(Yii::app()->user->hasFlash('error')): ?>

    <div class="flash-error"><?php echo Yii::app()->user->getFlash('error'); ?></div>

<?php endif;?>


<?php

//CGridView

$this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'artist-area-grid',

	'ajaxUpdate'=>false,//set to false

	'dataProvider'=>$model->search(),

	'filter'=>$model,

	'columns'=>array(

		'id',

		'name',

		'intro',

		array(

			'class'=>'CButtonColumn',

		),

	),

));

?>



Hi GSTAR,

I have been checking the code of the CGridView and when using CButtonColumn then even if you set the CButtonColumn property ‘buttons’ as array(‘delete’=>array(‘click’=>‘do something else’)) then the function of CButtomColumn initDefaultButtons states:




$this->buttons['delete']['click']=<<<EOD

function() {

	$confirmation

	$.fn.yiiGridView.update('{$this->grid->id}', {

		type:'POST',

		url:$(this).attr('href'),$csrf

		success:function() {

			$.fn.yiiGridView.update('{$this->grid->id}');

		}

	});

	return false;

}

EOD;




right at the end of the code. That means, that if you wish to tell the user that something has been successfully deleted it you have to create an object that extends CButtomColumn, override its initDefaultButtons and on that buttonID event (click) make an update of a layer that informs the user and afterwards calls the update (as exposed above).

I found that afterAjaxUpdate is not being called after a delete call has been performed but after $.fn.yiiGridView.update updates.

Other than that, we could workaround (very bad) that by overriding the click function of the delete button by registering a javascript script afterwards doing a jQuery(’#yiigridid a.delete’).die(‘click’) and then call .live(‘click’… again in order to create your own delete function.

This is the only solution I could find for your problem.

Thanks Antonio - this really did my head in so in the end I just created a new delete() function for my delete button :)

No problem G,

I didnt have much time lately, but I was also curious how all that works and found that the ‘delete’ button is the only one forced to be that js code above.

I think that by extending the CButtonColumn and then override the initDefaultButtons is the right solution.

Could be a good wiki :)

Congrats anyway G

why not you just throw new exception like this :




throw new CHttpException(400,'Sorry you can not delete this!');



The grid will recive error and will alert the exception. simple and effective.

Hello everything,

After couple of hours of pulling my hair I think I’ve come up with a better solution.

in Controller


try{

   $this->loadModel($id)->delete();

   Yii::app()->user->setFlash('deleteStatus','Deleted Successfully');

   echo "<div class='flash-success'>Deleted Successfully</div>"; //for ajax

}catch(CDbException $e){

    Yii::app()->user->setFlash('deleteStatus','One or more town is related with this region');

    echo "<div class='flash-error'>One or more town is related with this region</div>"; //for ajax

}

if(!isset($_GET['ajax']))

    $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin')); 

In View File


<?php $this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'region-grid',

	'dataProvider'=>$model->search(),

	'filter'=>$model,        

	'columns'=>array(

		'name',

		array(

			'class'=>'CButtonColumn',

                        'afterDelete'=>'function(link,success,data){ if(success) $("#statusMsg").html(data); }',

		),

	),

)); ?>

So the trick was inside the the delete button’s afterDelete event. Had to create an html id named statusMsg. I hope this will help someone…

I am trying to execute one javascript function when the delete operation is successful and I implemented the solution posted by you hasanavi, but it does not work because the ‘afterDelete’ property does not exist in Yii 1.1.6.

Sorry - forgot to add,

Thanks jogasa21

This is the best solution ever, even works with ajax. It redirects you to page where it says about error either pops up error message.


try

{

   $this->loadModel($id)->delete();

}

catch(CDbException $e)

{

   throw new CHttpException(400,'Sorry you can not delete this!');

}