Login Widget Ajax Not Working

Hi everybody,

I have spent a LOT of time searching for an answer to this problem, I’ve read tons of other forum posts from people who have problems with ajax and none of it applies. Of course, I’ve also tried endlessly to fix my problem and now, I come to you, completely confused and reeeaaaally wanting to overcome this dumb little problem.

[b]

Object Description: [/b]

I have a login field in the header of my Web App. No matter what page your on, it’s there, so I stuck the code into a widget that connects to a view that uses the ‘login’ action of my User Controller.

Problem Description:

I’ve decided against directing the user to a seperate login view if he sends wrong login data. I want Ajax Validation. Which I got to work just fine with the Registration form - an overlay that I stuck into my main layout using renderpartial. But frick, it just won’t work with the login form. I’ve -really- been working back and forth through what I did with the registration form and scrutenized the heck out of my login controller, views and widget.

But the problem, which is pretty simple, is that no ajax Post data is sent. None. I have all parameters set, just like with the registration form, but zip.

Important:

What must be said here is that all other functionality works. the error is displayed without ajax and the user is lgged in if the validation is successful, seriously, it’s beautiful. Just the Ajax is stubbornly refusing to work.

Thank you a million times in advance.

My Code:

The Widget:

LoginHead.php




<?php 

class LoginHead extends CWidget 

{


	public $model;

	public function run(){

			if (!Yii::app()->user->isGuest) {

				

				echo $this->render('loggedin', array('model'=>$this->model)); 

			}

			

			else if (Yii::app()->user->isGuest) {

				

					echo $this->controller->renderPartial('application.components.views.login', array('model'=>$this->model), true); 

			}

			


	}	


}	

?>



The View:

login.php




Noch nicht dabei? Jetzt

<div class="registerhead"> <a href="#" title="Kostenlos registrieren">Kostenlos registrieren </a></div>

Ansonsten...			

<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'login-form',

	'action'=>Yii::app()->createUrl('//user/login'),

	'htmlOptions'=>array('class'=>'ym-form'),

	'errorMessageCssClass'=>'ym-message',

	'enableAjaxValidation'=>true,

	'clientOptions'=>array('validateOnSubmit'=>true,),

	)); ?>

				<div class="username ym-fbox-text">

					<?php echo $form->textField($model,'user_email', array('id'=>'usernamehead') ); ?>

					<?php echo $form->error($model,'user_email'); ?>

				</div>

				<div class="secondlineheadlogin">

					<div class="password ym-fbox-text">

					<?php echo $form->passwordField($model,'password', array('id'=>'passwordhead')); ?>

					<?php echo $form->error($model,'password'); ?>


					</div>

					<div class="ym-fbox-button">

						<?php echo CHtml::ajaxSubmitButton('Login', array('type'=> 'submit')); ?>

					</div>

				</div>

				

					


<?php $this->endWidget(); ?>




The Action:

UserController.php/actionLogin()




public function actionLogin()

	{

		

		$model = new User('login');

		$this->model = $model;

		// if it is ajax validation request

		if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}

		if (isset($_POST['User'])) {

			$model->attributes=$_POST['User'];

			if($model->validate() && $model->login())

				$this->redirect(Yii::app()->user->returnUrl);

			else {

				$this->render('//site/index', array('model'=>$model));		

			}	

		}

				

	}



The Model:

User.php




<?php


/**

 * This is the model class for table "tbl_user".

 *

 * The followings are the available columns in table 'tbl_user':

 * @property string $username

 * @property string $user_email

 * @property string $name

 * @property string $vorname

 * @property string $password

 * @property string $passcheck

 *

 * The followings are the available model relations:

 * @property Material[] $materials

 * @property Nutzerantwort[] $nutzerantworts

 * @property Vote[] $votes

 */

class User extends CActiveRecord

{

	public $passcheck;

	

	public $_identity;

		

	/**

	 * Returns the static model of the specified AR class.

	 * @param string $className active record class name.

	 * @return User the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}


	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'tbl_user';

	}


	public function beforeSave(){

		if ($this->isNewRecord) { 

			$this->password = hash_hmac('sha256', $this->password, Yii::app()->params['encryptKey']);

		 }

		return parent::beforeSave();

	}

	

	/**

	 * @return array validation rules for model attributes.

	 */

	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('username, user_email,  password, passcheck', 'required', 'message'=>'Dieses Feld darf nicht leer sein.', 'on'=>'insert'),

			array('username, user_email', 'unique', 'message'=>'{attribute} {value} existiert bereits. ', 'on'=>'insert'),

			array('username, name, vorname', 'length', 'max'=>15, 'message'=>'{attribute} ist zu lang.', 'on'=>'insert'),

			array('user_email', 'length', 'max'=>60, 'message'=>'{attribute} ist zu lang.', 'on'=>'insert'),

			array('password, passcheck', 'length', 'max'=>100, 'message'=>'{attribute} ist zu lang.', 'on'=>'insert'),

			array('passcheck', 'compare', 'compareAttribute'=>'password', 'message'=>'Die Passwörter müssen genau gleich sein.', 'on'=>'insert'),

			array('password, user_email', 'required', 'on'=>'login'),

			array('password', 'authenticate', 'on'=>'login'),

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('username, user_email, name, vorname, password', 'safe', 'on'=>'search'),

		);

	}


	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

			'materials' => array(self::HAS_MANY, 'Material', 'username'),

			'nutzerantworts' => array(self::HAS_MANY, 'Nutzerantwort', 'username'),

			'votes' => array(self::HAS_MANY, 'Vote', 'username'),

		);

	}


	/**

	 * @return array customized attribute labels (name=>label)

	 */

	public function attributeLabels()

	{

		return array(

			'username' => 'Benutzername',

			'user_email' => 'E-Mail Adresse',

			'name' => 'Name',

			'vorname' => 'Vorname',

			'password' => 'Passwort',

			'passcheck' => 'Passwort wiederholen',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

	 */

	public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;


		$criteria->compare('username',$this->username,true);

		$criteria->compare('user_email',$this->user_email,true);

		$criteria->compare('name',$this->name,true);

		$criteria->compare('vorname',$this->vorname,true);

		$criteria->compare('password',$this->password,true);


		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}

	

	public function authenticate()

	{

		if(!$this->hasErrors())

		{

			$this->_identity=new UserIdentity($this->user_email,$this->password);

			if(!$this->_identity->authenticate())

				$this->addError('password','Falscher Benutzername oder Passwort.');

		}

	}


	/**

	 * Logs in the user using the given username and password in the model.

	 * @return boolean whether login is successful

	 */

	public function login()

	{

		if($this->_identity===null)

		{

			$this->_identity=new UserIdentity($this->user_email,$this->password);

			$this->_identity->authenticate();

		}

		if($this->_identity->errorCode===UserIdentity::ERROR_NONE)

		{

			Yii::app()->user->login($this->_identity);

			return true;

		}

		else

			return false;

	}

}



Hello, perhaps some of the solutions below could help :

  1. Have you tried setting the $processOutput of the renderPartial to be true ?



echo $this->controller->renderPartial('application.components.views.login', array('model'=>$this->model), true, true); 



  1. I’m working with a lot of ajax also right now. All the pages in my app are rendered using ajax and a few days ago I got stuck with ajax validation, and this is how I got it working ( in my case I am trying to insert new data and update the gridview below the form ) :




<?php $form = $this->beginWidget('CActiveForm', array(

                'id'=>$this->id.'-form',

    		'enableAjaxValidation'	 => true,

    		'enableClientValidation' => true,

    	        'clientOptions'	=> array(

			'validateOnSubmit'	=> true,

			'validateOnChange'	=> true,

			'beforeValidate'	=> "js:function(form) {													    

                                                           Loading.show();																		 

                                                           return true;																	 		                    

                                                    }",

													

                        'afterValidate'=>'js:function(form, data, hasError) {

															 

                                                 Loading.hide();

                                                 if (!hasError) {

																	 

                                                       $.ajax({																	 

                                                         "dataType" 	: "json",																	

                                                         "type" 	: "POST",																		       

                                                         "url"  	: "'.$url.'",																		

                                                         "data" 	: form.serialize(),																		

                                                         "success"	: function(data) {																							

                                                                  $("div.success-msg").html(data.msg);																							

                                                                  $.fn.yiiGridView.update("'.$gridId.'");																							

                                                                  return true;																					  

                                                                  }

																	

                                                       });

																

                                                 } 

															


                                          }'),

              'htmlOptions'=>array(

                       'onsubmit'=>"return false;", /* Disable normal form submit */

                       'enctype'=>'multipart/form-data'

              )

        )

);?>


...


<?php echo CHtml::ajaxSubmitButton(

          $model->isNewRecord? 'Add' : 'Edit','',

          array('beforeSend'=> 'js:$.yii.fix.ajaxSubmit.beforeSend("#'.$this->id.'-form")'), /* Works with CActiveForm : validateOnSubmit */

          array('id'=>'submit-btn-'.uniqid(), 'live'=>false)

); ?>




O, I forgot one thing. If you check at the firebug, are there any multiple registered script ? In my case, I display the views using tabs. If I open first tab, which containing cactiveform, everything works fine. But then I open the second tab ( which containing cactiveform also ), all ajax related function on my first tab stop. It is because multiple registered javascript files, such as jquery.yiiactiveform.js, jquery.yiigridview.js, etc.

So, I have to check manually whether the script is already registered or not before rendering the view, and after that everything works ok

Hi!

Thanks for the response, much appreciated.

  1. renderpartial processoutput

yep, tried that, if I do that, my entire JS goes bananas and stops working. Because THAT’S when I really do get multiple scripts registers.

  1. thanks, but I don’t quite understand what part of your code you mean I could apply to my problem. :)

  2. Sadly, no multiple binds, although that really would make me happy just because I could follow the error in that case…

Thank you for checking out my problem, though!

Much appreciated.

Hello, sorry for the late reply. Yes , you’re welcome. Have you found the solution yet ?

Hi, nope, still nothing. But I also was not sure which part of your code you meant that I should use.

Hi, try the beforeSend at the ajaxSubmitButton :




<?php echo CHtml::ajaxSubmitButton(

          $model->isNewRecord? 'Add' : 'Edit','',

          array('beforeSend'=> 'js:$.yii.fix.ajaxSubmit.beforeSend("#'.$this->id.'-form")'),

          array('id'=>'submit-btn-'.uniqid(), 'live'=>false)

); ?>