Ajax request redraws whole page (CListView here in particular)

Hi,

something that’s been bothering me for quite a while is that Yii in general retransmits the whole page upon an AJAX request. This makes sense if the ID hasn’t been explicitly specified and thus needs to be calculated I guess, but when you actually specify the ID of the div that should be updated, I cannot understand the reasoning behind it.

For my own widgets I have come up with a solution I’m quite happy with. For a given widget, say Commenting, I have a class CommentingAction extending Action. I then register one common controller WidgetController, which in turn refers to CommentingAction as the appropriate action. CommentingAction can then only re-run the widget Commenting if the request is an AJAX request, otherwise redirect the user to the correct page.

However, with CListView I find it conceivably hard to implement anything like this. Of course I’d like the buttons to work as they do now if the request is not AJAX. Otherwise, I’d like it to trigger some action that only returns the widget again, not the whole page. I cannot see any good implementation for this without either rewriting almost everything or possibly hacking something together.

Do you have any recommendations? What would be wrong with my (possibly quite heavy) feature request that AJAX requests should only redraw the one div tag if an ID has been explicitly specified?

Thanks,

Lupin

Never done like you asked but I have the same problem before so I create my own style of list view. My ajax did alter the HTML code in the page in order to redraw something. Not a very good solution since I didn’t utilize Yii’s CListView but worked for me. Also look forward to any answer to your question.

You can try something like this to render only the specific part you need:




public function beforeAction($action){

  if(Yii::app()->request->isAjaxRequest){

     $this->layout = false;

  }

}



That will make CController::render behave as if were renderPartial by not rendering the layout, that way only the result in your view will be returned in the ajax call, but normal calls will be sent with the template as normal.

(untested)

The problem is that this cannot work. CListView does not give links to some specific action but merely appends some GET parameters. As a result there is no way of telling which part of the view needs to be updated. So one must change the behavior of the buttons.

Thanks anyway!

Well with this, you’ll mainly update everything that is not part of the layout, its not exactly what you want, but it still saves some bandwidth and therefore load time.

I have been searching the forums for hours and trying different code with no luck.

I want my AJAX call to reload my widget, however it reloads the whole page in the <div id="poll123"> area.

It seems that right now in the Yii development it’s not possible to create an AJAX link that passes POST data to only the widget.

Disappointment? naahhh, there’s always a way. I would love it if I’m missing something! Please anyone?

<?php echo CHtml::ajaxLink("VOTE",

Yii::app()-&gt;createUrl('//COMPONENTS/MYWIDGET' ),  &lt;&lt;--- <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/huh.gif' class='bbc_emoticon' alt='???' />


	array(


		'update'=&gt;'#poll123',


		'type' =&gt; 'POST',


		'beforeSend'=&gt;'function(){&#036;(&#092;'body&#092;').undelegate(&#092;'#submitPoll'.&#036;a.'&#092;', &#092;'click&#092;');}',


	),


	array('id'=&gt;'submitPoll'.&#036;a, 'name'=&gt;'submitPoll')


);?&gt;

Ok, sorry if I answered my own question. From other posts, it seems this is the way to reload widget without recreating the whole page.

It seems that:

  1. The AJAX call has to go through a controller to get to the widget.

  2. The controller calls a _view file with render partial.

  3. Finally, that view file calls the widget.

>> part of view file /protected/components/view/_quickPollForm.php (part of widget view files)

<div id="poll123">

<FORM>

QUESTION 1

QUESTION 2

<?php echo CHtml::ajaxLink("VOTE",

Yii::app()->createUrl(’/widget/quickpoll’ ), <<— this calls the widget controller !!

array( ‘update’=>’#poll123’, ‘type’ => ‘POST’, ‘beforeSend’=>‘function(){$(\‘body\’).undelegate(\’#submitPoll’.$a.’\’, \‘click\’);}’, ),

array(‘id’=>‘submitPoll’.$a, ‘name’=>‘submitPoll’)

);?>

</FORM>

</div>

>> protected/controllers/WidgetController.php

public function actionQuickpoll( )


{


	&#036;this-&gt;renderPartial( '_quickPollView' );


}

– /protected/views/widget/_quickPollView

<?PHP $this->widget(‘application.components.QuickPoll’ );?>