I’m working on a widget, that does a lot of ajax calls to display data.
When I try to show a form through an ajax call from this widget,
some form elements will not work (CJuiDatePicker,…) because the javascript/clientScript code and the ‘js-bind’ is not submitted to the browser.
The problem is, that the main widget doesn’t have a ‘renderPartial’ like a controller, where I could set ‘processoutput=true’ to output the js-stuff.
A widget only has the render function without the possibility to output the generated registerClientScript code.
I didn’t test ‘$this->controller->renderPartial’ because the controller is not always the same and doesn’t know where to find the view file for the form and ‘$this’ in the view should be the widget itself not the controller.
I don’t know what the purpose of your widget is but maybe it is better to create a CAction that can be used by all controllers using the widget (CAutoComplete does that if I am correct). This way the widget could use $this->controller->controllerActionName which does the renderPartial.
The widget renders a input form and displays data by ajaxSubmit from this form.
For this purpose I have a CAction that handles the ajax responses.
In one of the ajax-call I want to reuse the widget-code to display the form as ajax-response, filled with specific values.
I just tried this
//main view -> OK
...
$this->widget('...FormWidget', array('model'=>$formModel)); //displays the form in the main view
//the CAction component that handles the ajax responses for the form widget
class FormWidgetAction extends CAction
{
....
// datepickers... doesn't work on ajax-response
protected function renderUpdateForm()
{
$model = ...
...
// I want to reuse the widget here to display the form filled with data ...
$this->controller->widget('FormWidget', array('model'=>$model));
}
/**
* Run the action
*/
public function run()
{
if (Yii::app()->request->isAjaxRequest)
{
$action = isset($_GET['action']) ? $_GET['action'] : null;
if (empty($action))
{
echo 'Param missing: action';
Yii::app()->end();
}
switch ($action)
{
case 'updateform':
$this->renderUpdateForm();
break;
case 'preview':
$this->renderPreview();
break;
....
default:
echo 'Unknown action: ' . $action;
}
Yii::app()->end();
}
}
}
So instead of passing in a relative path you force the controller to use a specific view not located in its own views folder but somewhere else. In this case the view is located in your widgets views folder.
I haven’t carefully read the entire thread but I think I could contribute a but here:
FWIW, I’m stuck on a similar problem: I have a module, which has a bundled widget within, and this widget is processing AJAX requests. Now, in order to render the views of this widget I’m doing something like:
While this trick to get render partial works, it works partially. While rendering the page initially, everything works fine, but for some reason when the AJAX call is processed, the entire page is rendered inside the small widget box. I think this isn’t a big surprise as the same has happened when initial rendering of widget occurred.
I’m contemplating between two solutions:
[list=1][]Doing some manual processing of the needed view file, echo, and "Yii::app()->end() (or simply die()…).[]Creating some super CPortlet class that will contain a renderPartial() method, as described here.[/list]
echo CJSON::encode(array( 'html' => $html)); //I echo as Json as I will need that in my ajax javascript functions later on.
Yii::app()->end();
[/list]
Thats it. The html variable you pass will be used as a reference by the client script and the corresponding script tags will be added to the html body.
Some background info of why this worked for me
I have a button that goes to a controller action, the action does some work and then renders a widget again to return to the view. The widget has some ajaxButtons and it renders some other widgets that also need some scripts to validate some forms. When I rendered the view for the first time, everything worked but when the widgets where rendered on the ajax call, they would not bring back the scripts therefore nothing worked anymore.
You may use the render method of the client script as an alternative, but this will also make the view retrieve the core scripts again (such as jquery and yiiactiveform). That is why I use the renderBodyBegin and renderBodyEnd instead, because I already have those scripts rendered in the view from the initial request.
I hope this solution works for someone. I am very happy and everything works for me now =)