Stupid Problem With An Action, Please Help

Hi All,

I’m completely stuck with one problem, I think that I’m missing something and it must be really stupid error, but… I can’t find the solution and I have tried, I think, with everything.

I have a form where I display a partial view, this partial view contains a table with a ajax button which launch an action, (no problem for now). Once the action is executed, this refresh the table (with a renderPartial), but… I can’t load the correct rows of my model!!!

For better understanding…

Here is my form with the partial view (views\post\_form.php):




<?php $form=$this->beginWidget('bootstrap.widgets.TbActiveForm', array(

    'id'=>'post-form',

	'type'=>'vertical',

	'enableAjaxValidation' => false,

	//This is very important when uploading files

	'htmlOptions' => array('enctype' => 'multipart/form-data'),

)); ?>


	<p class="note">Fields with <span class="required">*</span> are required.</p>


	<?php echo $form->errorSummary($model); ?>


	<div class="field">

		<?php echo $form->textFieldRow($model,'title',array('size'=>80,'maxlength'=>128)); ?>

	</div>


	<div class="field">

		<?php echo $form->textAreaRow($model,'content',array('rows'=>10, 'cols'=>70)); ?>

	</div>


	<div class="field">

		<?php echo $form->dropDownListRow($model,'status',PostLookup::items('PostStatus')); ?>

	</div>

	

        //Here I render a table

	<?php $this->renderPartial('/postmedia/_update', array('model' => $model->medias)); ?>

	

	<div class="actions field">

		<?php $this->widget('bootstrap.widgets.TbButton',array(

                    'buttonType'=>'submit',

                    'type'=>'success',

                    'label'=>$model->isNewRecord ? 'Create' : 'Save',

                    'size'=>'large',

                    //'htmlOptions'=>array('class'=>'btn btn-success btn-medium')

                 )); ?>

	</div>


<?php $this->endWidget(); ?>



Here the partial view (\views\postMedia\_update.php):




<table class="table striped" id="down">

    <tbody class="images"></tbody>


    <?php foreach($model as $photo) : ?>

        <tr class="fade in" style="height: 53px;">

        

            <td class="preview">

                <a href="<?php $photo->url . $photo->filename?>" title="<?php echo $photo->filename; ?>" rel="gallery" download="<?php echo $photo->filename; ?>"></a>

            </td>

            <td class="name">

                <a href="<?php echo Yii::app()->baseUrl . $photo->url . $photo->filename?>" title="<?php echo $photo->filename; ?>" rel="image" download="<?php echo $photo->filename; ?>"><?php echo $photo->filename; ?></a>

            </td>

            <td class="size"><span><?php echo $photo->size; ?></span></td>

            <td class="button">

                  <?php $this->widget('bootstrap.widgets.TbButton',array(

                      'buttonType'=>'ajaxButton',

                      'type'=>'danger',

                      'label'=>'Remove',

                      'size'=>'normal',

                      'icon'=>'icon-trash icon-white',

                      'htmlOptions'=>array(

                          'href'=>Yii::app()->createUrl('/postmedia/ajaxdelete', array('id'=>$photo->id)),

                      ),

                      'ajaxOptions'=>array(

                          'update'=>'#down', 

                          'url'=>Yii::app()->createUrl('/postmedia/ajaxdelete', array('id'=>$photo->id)),

                          'type'=>'POST',

                      ),

                  )); ?>

							

            </td>

        </tr>

    <?php endforeach; ?>

</table>



And here the action (\controllers\PostMediaController.php):




    public function actionAjaxDelete()

	{

	    

	    Yii::log("ANTES 0 id: " .$_GET['post_id'], "info");

		

	    if(Yii::app()->request->isPostRequest && isset($_GET['id']))

		{

			

                    //$media = $this->loadModel($id);	

                    $media = PostMedia::model()->findByPk($_GET['id']);			

                    

                    Yii::log("ANTES 1 media->post_id: " .$media->post_id, "info");

	

                    $medias=new CActiveDataProvider(PostMedia::model(), array(

                        'criteria'=>array(

                            'condition'=>'post_id='.$media->post_id,

                        ),

                    ));


                    //$medias = Post::model()->findByPk($media->post_id);

		    

			foreach($medias as $photo):

			    Yii::log("MEDIA id: " .$photo->id, "info");

				Yii::log("MEDIA url: " .$photo->url, "info");

				Yii::log("MEDIA filename: " .$photo->filename, "info");

				Yii::log("MEDIA post_id: " .$photo->post_id, "info");

			endforeach;

									

                    $this->loadModel($_GET['id'])->delete();

			

                    Yii::log("ANTES 2", "info");

		    			

                    echo $this->renderPartial('_update', array('model'=>$medias), true);

                    return;			

                }

		else

                    throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');

	}



As you can see, I perform an ‘echo’ with the partial view and the model instance, but the model instance is not well loaded, it seems loaded with garbage, as it returns some empty rows, I see it because it writes this on the log:




2013/03/17 04:53:02 [info] [application] ANTES 0 id: 

2013/03/17 04:53:02 [info] [application] ANTES 1 media->post_id: 21

2013/03/17 04:53:02 [info] [application] MEDIA id: 

2013/03/17 04:53:02 [info] [application] MEDIA url: 

2013/03/17 04:53:02 [info] [application] MEDIA filename: 

2013/03/17 04:53:02 [info] [application] MEDIA post_id: 

2013/03/17 04:53:02 [info] [application] MEDIA id: 

2013/03/17 04:53:02 [info] [application] MEDIA url: 

2013/03/17 04:53:02 [info] [application] MEDIA filename: 

2013/03/17 04:53:02 [info] [application] MEDIA post_id: 

2013/03/17 04:53:02 [info] [application] MEDIA id: 

2013/03/17 04:53:02 [info] [application] MEDIA url: 

2013/03/17 04:53:02 [info] [application] MEDIA filename: 

2013/03/17 04:53:02 [info] [application] MEDIA post_id: 

2013/03/17 04:53:02 [info] [application] ANTES 2



If someone could tell me what I’m doing wrong… It would be really appreciate, I have tried everything and I don’t get this simple thing! :S

Hi menxaca,

It’s a common misunderstanding among new users, but CActiveDataProvider is not an array of data fetched from db. It is a kind of query executor that is mainly meant to be used by CGridView or CListView. The grid and the list call its getData() method to fetch data from db.

So, try instead:




     $dp = new CActiveDataProvider(PostMedia::model(), array(

        'criteria'=>array(

             'condition'=>'post_id='.$media->post_id,

        ),

     ));

    $medias = $dp->getData();



Or, the following seems more appropriate for your scenario.




    $medias = PostMedia::model()->findAllByAttribute(array('post_id'=>$media->post_id));



Hi softark!

I have to say… THANK YOU! It made my day!

The first approach works perfectly fine (I didn’t know about getData function). I also tried the second approach but I get this error:




exception 'CException' with message 'PostMedia and its behaviors do not have a method or closure named "findAllByAttribute".' in C:\AppServ\www\yii4\framework\base\CComponent.php:266



I already tried this before posting and that’s why I got desperated, just curious about why findAllByAttribute doesn’t work…

Thanks again!

Ah, sorry.

Not findAllByAttribute but findAllByAttributes

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

The class reference looks a bit hard to read at a first glance, but it’s really a nice document. :)

It seems that I’m kind of blind, I didn’t realize it!

You have been really helfull, thank you so much :)

:( after one problem there is always another…

The ajax button and renderPartial doesn’t work as expected. I have realized that when the partial view ‘\views\postMedia\_update.php’ is rendered, the button’s action showed in every row of the table aren’t right and I explain…

That partial view displays a table with N record from DB, the ajax button deletes a single row, the code for the ajax button is:




<td class="button">

                  <?php $this->widget('bootstrap.widgets.TbButton',array(

                      'buttonType'=>'ajaxButton',

                      'type'=>'danger',

                      'label'=>'Remove',

                      'size'=>'normal',

                      'icon'=>'icon-trash icon-white',

                      'htmlOptions'=>array(

                          'href'=>Yii::app()->createUrl('/postmedia/ajaxdelete', array('id'=>$photo->id)),

                      ),

                      'ajaxOptions'=>array(

                          'update'=>'#down', 

                          'url'=>Yii::app()->createUrl('/postmedia/ajaxdelete', array('id'=>$photo->id)),

                          'type'=>'POST',

                      ),

                  )); ?>                                                        

            </td>



Lets say we have on DB table this information:




ID        Image

---------------

1         Image1

2         Image2

3         Image3



When I load the page for the first time, the table showed in the partial view is this:




ID        Image        AjaxButton

---------------------------------

1         Image1       action: /postmedia/ajaxdelete/id/1

2         Image2       action: /postmedia/ajaxdelete/id/2

3         Image3       action: /postmedia/ajaxdelete/id/3



Everthing is correct for now, but… if I click in the first button in order to delete the first row, the table gets refreshed thanks to the ajax action in this way:




ID        Image        AjaxButton

---------------------------------

2         Image2       action: /postmedia/ajaxdelete/id/1 //The action has not changed!

3         Image3       action: /postmedia/ajaxdelete/id/3



Everything has been refresed except the action button!!! therefore if I tried to delete the row it passes a wrong ID, already deleted, so strange! I have put logs to see what information gets into the partial view and the info is correct!

Why this is happening? Please help, I don’t know what else I can check…

OMG… this only happen with the first row, if I start to delete from the bottom it works! The incredible of this is that the action url showed in the logs, just before render the button, is correct!

As far as I know, it’s not safe to have an ajax button or link in the element that will be updated by ajax.

I would create an ordinary button or link and manually attach an event handler to it using jQuery.on.

Something like:




// in the partial view

<td class="button">

	<?php $this->widget('bootstrap.widgets.TbButton',array(

		'type'=>'danger',

		'label'=>'Remove',

		'size'=>'normal',

		'icon'=>'icon-trash icon-white',

		'url' => Yii::app()->createUrl('/postmedia/ajaxdelete', array('id'=>$photo->id)),

		'htmlOptions'=>array(

			'class'=>'delete-media',

		),

	)); ?>

</td>


// in the main view

...

$('body').on('click', '.delete-media', function(event){

	$.ajax({

		'type' : 'POST',

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

		'success' : function(data){

			$('#down').html(data);

		}

	});

	event.preventDefault();

});



Not tested, and may have some error because I’m not familiar with the bootstrap button.

But the point is that I would place my event handler outside of the ajax updated region.

You are an authentic GENIUS!

Awesome! That’s was the reason! I’m not familiar with js, but thanks to you… learning…learning…

One more time… THANKS!