Skip to content
Permalink
Browse files

Fixes #938: added `yii\web\View::renderAjax` and `yii\web\Controller:…

…:renderAjax`.
  • Loading branch information
qiangxue committed Jan 28, 2014
1 parent 861c2b2 commit 02b908bd9c85520683d2cbfa98b8aad24f4724a2
Showing with 90 additions and 13 deletions.
  1. +20 −0 framework/web/Controller.php
  2. +70 −13 framework/web/View.php
@@ -16,6 +16,8 @@
*
* @property string $canonicalUrl The canonical URL of the currently requested page. This property is
* read-only.
* @property View $view The view object that can be used to render views or view files. This property is
* read-only.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
@@ -32,6 +34,24 @@ class Controller extends \yii\base\Controller
*/
public $actionParams = [];


/**
* Renders a view in response to an AJAX request.
*
* This method is similar to [[renderPartial()]] except that it will inject into
* the rendering result with JS/CSS scripts and files which are registered with the view.
* For this reason, you should use this method instead of [[renderPartial()]] to render
* a view to respond to an AJAX request.
*
* @param string $view the view name. Please refer to [[render()]] on how to specify a view name.
* @param array $params the parameters (name-value pairs) that should be made available in the view.
* @return string the rendering result.
*/
public function renderAjax($view, $params = [])
{
return $this->getView()->renderAjax($view, $params, $this);
}

/**
* Binds the parameters to the action.
* This method is invoked by [[Action]] when it begins to run with the given parameters.
@@ -127,6 +127,38 @@ class View extends \yii\base\View

private $_assetManager;

/**
* Renders a view in response to an AJAX request.
*
* This method is similar to [[render()]] except that it will surround the view being rendered
* with the calls of [[beginPage()]], [[head()]], [[beginBody()]], [[endBody()]] and [[endPage()]].
* By doing so, the method is able to inject into the rendering result with JS/CSS scripts and files
* that are registered with the view.
*
* @param string $view the view name. Please refer to [[render()]] on how to specify this parameter.
* @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file.
* @param object $context the context that the view should use for rendering the view. If null,
* existing [[context]] will be used.
* @return string the rendering result
* @see render()
*/
public function renderAjax($view, $params = [], $context = null)
{
$viewFile = $this->findViewFile($view, $context);

ob_start();
ob_implicit_flush(false);

$this->beginPage();
$this->head();
$this->beginBody();
echo $this->renderFile($viewFile, $params, $context);
$this->endBody();
$this->endPage(true);

return ob_get_clean();
}

/**
* Registers the asset manager being used by this view object.
* @return \yii\web\AssetManager the asset manager. Defaults to the "assetManager" application component.
@@ -147,8 +179,11 @@ public function setAssetManager($value)

/**
* Marks the ending of an HTML page.
* @param boolean $ajaxMode whether the view is rendering in AJAX mode.
* If true, the JS scripts registered at [[POS_READY]] and [[POS_LOAD]] positions
* will be rendered at the end of the view like normal scripts.
*/
public function endPage()
public function endPage($ajaxMode = false)
{
$this->trigger(self::EVENT_END_PAGE);

@@ -159,7 +194,7 @@ public function endPage()
echo strtr($content, [
self::PH_HEAD => $this->renderHeadHtml(),
self::PH_BODY_BEGIN => $this->renderBodyBeginHtml(),
self::PH_BODY_END => $this->renderBodyEndHtml(),
self::PH_BODY_END => $this->renderBodyEndHtml($ajaxMode),
]);

$this->metaTags = null;
@@ -450,25 +485,47 @@ protected function renderBodyBeginHtml()
/**
* Renders the content to be inserted at the end of the body section.
* The content is rendered using the registered JS code blocks and files.
* @param boolean $ajaxMode whether the view is rendering in AJAX mode.
* If true, the JS scripts registered at [[POS_READY]] and [[POS_LOAD]] positions
* will be rendered at the end of the view like normal scripts.
* @return string the rendered content
*/
protected function renderBodyEndHtml()
protected function renderBodyEndHtml($ajaxMode)
{
$lines = [];

if (!empty($this->jsFiles[self::POS_END])) {
$lines[] = implode("\n", $this->jsFiles[self::POS_END]);
}
if (!empty($this->js[self::POS_END])) {
$lines[] = Html::script(implode("\n", $this->js[self::POS_END]), ['type' => 'text/javascript']);
}
if (!empty($this->js[self::POS_READY])) {
$js = "jQuery(document).ready(function(){\n" . implode("\n", $this->js[self::POS_READY]) . "\n});";
$lines[] = Html::script($js, ['type' => 'text/javascript']);
}
if (!empty($this->js[self::POS_LOAD])) {
$js = "jQuery(window).load(function(){\n" . implode("\n", $this->js[self::POS_LOAD]) . "\n});";
$lines[] = Html::script($js, ['type' => 'text/javascript']);

if ($ajaxMode) {
$scripts = [];
if (!empty($this->js[self::POS_END])) {
$scripts[] = implode("\n", $this->js[self::POS_END]);
}
if (!empty($this->js[self::POS_READY])) {
$scripts[] = implode("\n", $this->js[self::POS_READY]);
}
if (!empty($this->js[self::POS_LOAD])) {
$scripts[] = implode("\n", $this->js[self::POS_LOAD]);
}
if (!empty($scripts)) {
$lines[] = Html::script(implode("\n", $scripts), ['type' => 'text/javascript']);
}
} else {
if (!empty($this->js[self::POS_END])) {
$lines[] = Html::script(implode("\n", $this->js[self::POS_END]), ['type' => 'text/javascript']);
}
if (!empty($this->js[self::POS_READY])) {
$js = "jQuery(document).ready(function(){\n" . implode("\n", $this->js[self::POS_READY]) . "\n});";
$lines[] = Html::script($js, ['type' => 'text/javascript']);
}
if (!empty($this->js[self::POS_LOAD])) {
$js = "jQuery(window).load(function(){\n" . implode("\n", $this->js[self::POS_LOAD]) . "\n});";
$lines[] = Html::script($js, ['type' => 'text/javascript']);
}
}

return empty($lines) ? '' : implode("\n", $lines);
}
}

6 comments on commit 02b908b

@Ragazzo

This comment has been minimized.

Copy link
Contributor

@Ragazzo Ragazzo replied Jan 28, 2014

Any official docs on this feature?

@qiangxue

This comment has been minimized.

Copy link
Member Author

@qiangxue qiangxue replied Jan 28, 2014

Only the API doc. Not sure where to write the guide doc about this.

@Ragazzo

This comment has been minimized.

Copy link
Contributor

@Ragazzo Ragazzo replied Jan 28, 2014

I think in controller, since in general it belongs to it. small Examples section would be very helpful.

@qiangxue

This comment has been minimized.

Copy link
Member Author

@qiangxue qiangxue replied Jan 28, 2014

Done in view.md.

@samdark

This comment has been minimized.

Copy link
Member

@samdark samdark replied Jan 28, 2014

I think view.md is suitable even if it will be used in controller.

@Ragazzo

This comment has been minimized.

Copy link
Contributor

@Ragazzo Ragazzo replied Jan 29, 2014

Yeah, but still docs are simple one sentence, while i whould like to see some clear examples on it, anyway fine with me.

Please sign in to comment.
You can’t perform that action at this time.