From 02b908bd9c85520683d2cbfa98b8aad24f4724a2 Mon Sep 17 00:00:00 2001 From: Qiang Xue <qiang.xue@gmail.com> Date: Tue, 28 Jan 2014 14:03:39 -0500 Subject: [PATCH] Fixes #938: added `yii\web\View::renderAjax` and `yii\web\Controller::renderAjax`. --- framework/web/Controller.php | 20 ++++++++++++++++++++ framework/web/View.php | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 90 insertions(+), 13 deletions(-) diff --git a/framework/web/Controller.php b/framework/web/Controller.php index 842028e..6923883 100644 --- a/framework/web/Controller.php +++ b/framework/web/Controller.php @@ -16,6 +16,8 @@ use yii\helpers\Html; * * @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. diff --git a/framework/web/View.php b/framework/web/View.php index 22fd3e3..75854aa 100644 --- a/framework/web/View.php +++ b/framework/web/View.php @@ -128,6 +128,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 @@ class View extends \yii\base\View /** * 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 @@ class View extends \yii\base\View 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 @@ class View extends \yii\base\View /** * 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); } } -- libgit2 0.27.1