Ajax Login form with validation errors inside jQuery modal dialog

I would like to share my little experience with Yii to the community in the form of the below small wiki:

I will demonstrate the user login and logout functionality along with validation errors using aweswome Yiiframework. The blog demo supplied with the standard framework download, provides a simple user login/logout functionality to demonstrate the core framework features. We will add some Ajax functions to this to display login form inside a jQuery modal dialog box with login errors if any. I do make use of ajaxSubmitButton( inside CActiveForm) to add ajax code to the submit button, CJuiDialog for modal dialog box. I will also show you how to separate login action(actionLogin in SiteController) into a separate class file(getLogin) that extends CAction, and later use this class as an action dynamically inside any controller. I use a widget class(loginProvider) and its action(GetLogin) for this purpose. I will now show you what modifications need to be done to the demo application:

  • Create a file named loginProvider.php and place it inside the components directory.
class loginProvider  extends CWidget{
    public static function actions(){
        return array(
    public function run(){
    protected function renderContent(){
 echo '<span style="float:right;">';
            echo CHtml::link('Login', array('/site/login.GetLogin'), array('onclick'=>'$("#login-dialog").dialog("open"); return false;'));
     echo '</span>';
     $this->getController()->renderPartial('application.components.views.login',array('model'=>new LoginForm)); 
     echo CHtml::link('Logout ('.Yii::app()->user->name.')', array('site/logout'), array('visible'=>!Yii::app()->user->isGuest));
 echo '</span>';
  • Create a directory named actions inside components directory.
  • Create the action class with name getLogin.php and place it inside components/actions directory.
class getLogIn extends CAction{
      public function run() {
            if (!defined('CRYPT_BLOWFISH')||!CRYPT_BLOWFISH)
    throw new CHttpException(500,"This application requires that PHP was compiled with Blowfish support for crypt().");
     $model=new LoginForm;
     if (Yii::app()->request->isAjaxRequest){ 
           if (isset($_POST['LoginForm'])) {  
          if ($model->validate() && $model->login()){
                $array = array("login" => "success");
                              Yii::app()->user->setFlash("success", "Successfully logged in.");
                              $json = json_encode($array);
                              echo $json;
         echo CActiveForm::validate($model);
           } //POST
  • Create a file named login.php and place it inside components/views with the following contents:
<?php $this->beginWidget('zii.widgets.jui.CJuiDialog',array(
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
                'method' => 'POST',
)); ?>
Please fill out the following form with your login credentials:</p>
<p class="note">
Fields with <span class="required">*</span> are required.</p>
<div id="login-error-div" class="errorMessage" style="display: none;">
<div class="row">
  <?php echo $form->labelEx($model,'username'); ?>
  <?php echo $form->textField($model,'username',array("onfocus"=>"$('#login-error-div').hide();")); ?>
  <?php //echo $form->error($model,'username'); ?>
<div class="row">
  <?php echo $form->labelEx($model,'password'); ?>
  <?php echo $form->passwordField($model,'password',array("onfocus"=>"$('#login-error-div').hide();")); ?>
  <?php //echo $form->error($model,'password'); ?>
  <p class="hint">
   Hint: You may login with <tt>demo/demo</tt>.
<div class="row rememberMe">
  <?php echo $form->checkBox($model,'rememberMe'); ?>
  <?php echo $form->label($model,'rememberMe'); ?>
  <?php echo $form->error($model,'rememberMe'); ?>
<div class="row submit">
  <?php echo CHtml::ajaxSubmitButton(
                                'Sign In',
                'beforeSend' => 'function(){ 
                                        'complete' => 'function(){ 
                                             $("#user_login_form").each(function(){ this.reset();});
                                             var obj = jQuery.parseJSON(data); 
                                            // View login errors!
         // alert(data);
                                             if(obj.login == "success"){
Login Successful! Please Wait...</h4>
                                         parent.location.href = "/";
                                                $("#login-error-div").html("Login failed! Try again.");$("#login-error-div").append("
                         array("id"=>"login","class" => "btn btn-primary")      
                ); ?>
<?php $this->endWidget(); ?>
<!-- form -->
<?php $this->endWidget('zii.widgets.jui.CJuiDialog'); ?>
  • Go to the main layout(blog/protected/views/layouts/main.php) and apply the following changes in the menu:
<div id="mainmenu">
  <?php $this->widget('zii.widgets.CMenu',array(
    array('label'=>'Home', 'url'=>array('post/index')),
    array('label'=>'About', 'url'=>array('site/page', 'view'=>'about')),
    array('label'=>'Contact', 'url'=>array('site/contact')),
    //array('label'=>'Login', 'url'=>array('site/login'), 'visible'=>Yii::app()->user->isGuest),
    //array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('site/logout'), 'visible'=>!Yii::app()->user->isGuest)
  )); ?>
  <?php $this->widget('loginProvider'); ?>
<!-- mainmenu -->

  • Finally, Go to SiteController(/blog/protected/controllers/SiteController) and append 'login.' action inside actions() method. Now, the login action is accessed as '/site/login.GetLogin'
class SiteController extends Controller
public function actions()
  return array(
   // captcha action renders the CAPTCHA image displayed on the contact page
   // page action renders "static" pages stored under 'protected/views/site/pages'
   // They can be accessed via: index.php?r=site/page&view=FileName
   'login.' =>  array('class'=>'application.components.loginProvider'),  
3 0
Viewed: 41 509 times
Version: 1.1
Category: Tutorials
Written by: pravi
Last updated by: Maxxer
Created on: Sep 14, 2013
Last updated: 6 years ago
Update Article


View all history