Using a widget located in a module as an AJAX action provider

Submitted by boaz on Sunday, May 20, 2012.

This issue bugged me for a few good hours until I found its solution:

I have this custom Yii Framework module that handles polls. This module contains an extension, which is a Yii "Portlet" (which is itself a CWidget). Now, this extension shows some poll, enabled voting, and once voted it replaces its content with the result of the poll thus far. All this activity should be done using AJAX: poll voting, replace of content with results.

The problem is that no matter what I did I ended up rendering the entire Yii page inside the tiny portlet box. The ajax was targeted at "current URL" as the widget was answering the AJAX call, noticing the vote, and I hoped that ti would be able to return the resulted HTML back to be used on client side to replace the current box content with (using CHtml::ajaxSubmitButton()). The code in the widget that handled the biz logic regarding voting, deciding which view to render, bookkeeping - was all inside the portlet renderContent() method (which I know doesn't sound too good but considering the concept and design of CPortlet I thought it does make up for a good design).

Problem was that since the AJAX call was always done for 'current page', those "current controller" and "current action" thingies did take place and was actually the cause for the complete rendering of the page inside the portlet view.
No matter what I did - I already used renderPartial() from with the widget, die(), echo directly, etc, I wasn't able the get rid of the rendering of the site within a site.

Solution?:
I created a simple controller inside the poll module, named ResultsSupplierController and within it actionProcessVote() method. This method runs the widget as if it was run in a view file--> $results = $this->widget('PollWidget', array(), true)  but notice the final parameter to the function - 'true'. This causes the output not to be rendered directly but rather sent back to the client ($results in this case). and the line after this one is naturally a "echo $result". This causes the widget to renderPartial as its supposed to, and this is indeed a partial content, which is sent back to the client that requested it, AJAXly. The client side JS takes this content and plants it appropriately.

So finally - I got it working! :-)

Leave a Comment

Fields with * are required.