Nowadays, it's common when part of a page is loaded asynchronously, that is, without reloading the rest of the page. Let's implement the quotes box, which will display random quotes and will have the Next quote link to show the next one.
yiic webapp
as described in the official guide.Carry out the following steps:
protected/controllers/QuoteController.php
as follows:<?php class QuoteController extends Controller { private $quotes = array( array('Walking on water and developing software from a specification are easy if both are frozen.', 'Edward V Berard'), array('It always takes longer than you expect, even when you take into account Hofstadter’s Law.', 'Hofstadter’s Law'), array('Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.', 'Rick Osborne'), array('I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone.', 'Bjarne Stroustrup'), array('Java is to JavaScript what Car is to Carpet.', 'Chris Heilmann'), ); private function getRandomQuote() { return $this->quotes[array_rand($this->quotes)]; } function actionIndex() { $this->render('index', array( 'quote' => $this->getRandomQuote() )); } function actionGetQuote() { $this->renderPartial('_quote', array( 'quote' => $this->getRandomQuote(), )); } }
protected/views/quote/index.php
:<h2>Quote of the day</h2> <div id="quote-of-the-day"> <?php $this->renderPartial('_quote', array( 'quote' => $quote, ))?> </div> <?php echo CHtml::ajaxLink('Next quote', array('getQuote'), array('update' => '#quote-of-the-day'))?>
The second view named protected/views/quote/_quote.php
is as follows:
“<?php echo $quote[0]?>”, <?php echo $quote[1]?>
First, we define a list of quotes in the controller's private property, $quotes
, and create a method to get a random quote. In a real application, you will probably get a quote from a database using DAO, the query builder, or an Active Record.
Then, we define a view for the index
action and _quote
, which is used in the getQuote
action that renders it without layout and the index
view as a partial. In the view action, we use CHtml::ajaxLink
to create a link that makes a request to the getQuote
action and updates the HTML element with the ID of quote-of-the-day
. This is done with a response CHtml::ajaxLink
that generates the following code in the resulting HTML page (reformatted):
<script type="text/javascript"> /*<![CDATA[*/ jQuery(function($) { jQuery('body').delegate('#yt0','click',function(){ jQuery.ajax({ 'url':'/quote/getQuote', 'cache':false, 'success':function(html){ jQuery("#quote-of-the-day").html(html) } }); return false; }); }); /*]]>*/ </script>
As jQuery is being used, Yii includes it in the page automatically and does so only once, no matter how many times we are using it.
You can see that Yii generated a #yt0
ID for us. That is great because you don't have to worry about setting IDs manually. Nevertheless, if you are loading a part of the page through AJAX and this part includes JavaScript-enabled widgets or the CHtml
AJAX helpers, then you need to set IDs manually because of a possible ID intersection.
If you want to customize the success
callback, then you can do this by setting it through a third parameter as follows:
<?php echo CHtml::ajaxLink('Next quote', array('getQuote'), array('success' => new CJavaScriptExpression('function(data){ alert(data); }')))?>
In some cases, it is not desirable to allow a non-AJAX access to the getQuote
action. There are two ways that we can limit its usage to AJAX-only. First, you can use the built-in ajaxOnly
filter as follows:
class QuoteController extends Controller { function filters() { return array( 'ajaxOnly + getQuote', ); } …
After adding this, a user who tries to use the getQuote
action directly will get a 400 Bad Request
HTTP error.
The second way is to detect if a request is made through AJAX with a special request
method. For example, if we want to show the standard 404 not found page, we can do this as follows:
function actionGetQuote() { if(!Yii::app()->request->isAjaxRequest) throw new CHttpException(404); $this->renderPartial('_quote', array( 'quote' => $this->getRandomQuote(), )); }
Similarly, we can use one action to serve both AJAX and non-AJAX responses:
function actionGetQuote() { $quote = $this->getRandomQuote(); if(Yii::app()->request->isAjaxRequest) { $this->renderPartial('_quote', array( 'quote' => $quote, )); } else { $this->render('index', array( 'quote' => $quote, )); } }
Sometimes, you need to suppress including a bundled jQuery, for example, if your project code uses a custom way of including JavaScript. To achieve this, you need to configure a clientScript
application component using protected/config/main.php
as follows:
return array( // … // application components 'components'=>array( // … 'clientScript' => array( 'scriptMap' => array( 'jquery.js'=>false, 'jquery.min.js'=>false, ), ), ), // … );
If you want to use your own specific version of jQuery instead, you can do so in the following way:
return array( // … // application components 'components'=>array( // … 'clientScript' => array( 'scriptMap' => array( 'jquery.js'=>'/js/jquery-1.4.2.js', 'jquery.min.js'=>'/js/jquery-1.4.2.min.js', ), ), ), // … );
For further information, refer to the following URLs:
18.217.6.114