Widget as Action Provider

CWidget, unlike CController, cannot have its own actions callable from outside, although it can define them in its static method actions() for later importing into the controller which owns the widget. The problem is to convey the result of running such an action into the widget at the point where the latter is used (e.g. in some view of the controller). Apparently, there is no communication whatsoever between the action and the widget. The action, although defined in the widget, is run by the controller which owns that widget. After reading the API doc, the only way I see this communication can be established is something like this:

[list=1][]Define a couple of properties at the receiving end (in the widget class), e.g. "actionID" and "actionContent".[]Define actions() and import them into the controller as described in the API doc.[]Determine some "native" (not "imported") controller action(s) or other method(s) which use and display the widget.[]Write code for the actions to be imported (it should be in separate classes derived from CAction) and embed in them call(s) to the method(s) determined above. These calls should pass action results to those methods for later passing them on to the widget either directly or via some view of the controller.[]Make sure those controller actions receive the data from "imported" actions of the widget and pass it on to the widget as properties ("actionID" and "actionContent" in our example).[]Make sure the widget in its init() and run() methods processes thus received data and adjusts its presentation accordingly.[/list]

Pretty long way, eh?

Am I wrong and is there a better way to couple CWidget with its CAction?

Can you maybe supply some simple code examples? I’m not sure if i understand what you mean with e.g. 4:

I guess, you already had a look ad CCaptcha and how the separation of widget display <-> widget actions is handled there.

I mean that e.g. CCaptchaAction should pass the result of its execution to some controller’s method which outputs a layout view:




$result=$this->getController()->createUrl($this->getId(),array('v'=>uniqid()));

$this->getController()->someActionWithLayout($result);



In this case someActionWithLayout() would instantiate a view which uses a CCaptcha widget instance and pass $result to it.

Yes, but CCaptcha does not have the actions() method and CCaptchaAction is supposed to be defined directly in the controller, that is, no actions() importing is involved here. Besides, CCaptchaAction’s output is used without any layout - either as a separate image file or as a link fetched via AJAX for embedding into the page at the client side.

All this means that there is no communication between CCaptcha and CCaptchaAction at the server side. Are there any examples where such communication actually takes place?

Umm you can use runController to run any action you want…

http://www.yiiframework.com/doc/api/CWebApplication#runController-detail