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.
View
@@ -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.

Show comment
Hide comment
@Ragazzo

Ragazzo Jan 28, 2014

Contributor

Any official docs on this feature?

Contributor

Ragazzo replied Jan 28, 2014

Any official docs on this feature?

@qiangxue

This comment has been minimized.

Show comment
Hide comment
@qiangxue

qiangxue Jan 28, 2014

Member

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

Member

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.

Show comment
Hide comment
@Ragazzo

Ragazzo Jan 28, 2014

Contributor

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

Contributor

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.

Show comment
Hide comment
@qiangxue

qiangxue Jan 28, 2014

Member

Done in view.md.

Member

qiangxue replied Jan 28, 2014

Done in view.md.

@samdark

This comment has been minimized.

Show comment
Hide comment
@samdark

samdark Jan 28, 2014

Member

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

Member

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.

Show comment
Hide comment
@Ragazzo

Ragazzo Jan 29, 2014

Contributor

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

Contributor

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.