Scriptbaker
SCRIPTBAKERAI & Software Engineering
JavaScript

Ajax-Based Yii Login Form

Learn how to create an AJAX-based Yii 1.1 login form without a full page refresh. This step-by-step guide explains how to use CActiveForm validation, the afterValidate callback, jQuery AJAX, and Yii controllers to validate credentials, authenticate users, handle errors, and redirect users with a JSON response.

· 5 min read · By Tahir Yasin

A traditional login form submits the page to the server and reloads the browser after the request is completed. For a better user experience, you can submit the login form asynchronously using AJAX. This allows Yii to validate the form, authenticate the user, and return the result without refreshing the page.

In this tutorial, we will create an AJAX-based Yii 1.1 login form using CActiveForm, jQuery AJAX, and a Yii controller action. The form will first use Yii's client-side validation. If there are no validation errors, JavaScript will intercept the normal submission and send the login request through AJAX.

What We Will Build

The login flow will work like this:

  1. The user enters a username and password.
  2. Yii validates the form fields.
  3. If validation errors exist, Yii displays them without submitting the login request.
  4. If validation succeeds, JavaScript serializes the form data.
  5. The credentials are sent to the Yii controller through an AJAX POST request.
  6. The controller authenticates the user.
  7. If authentication succeeds, the browser redirects the user to the appropriate URL.
  8. If authentication fails, the returned errors are displayed inside the form.

Why Use AJAX for a Yii Login Form?

AJAX form submission can make a login interface feel faster because the browser does not need to reload the entire page for every request. It also gives you more control over loading states, validation messages, authentication responses, and redirects.

Yii provides client-side and AJAX validation functionality through its form components. However, validation and form submission are separate concerns. In this Yii 1.1 example, we use the validation callback to prevent the default submission and then send the valid form data through jQuery's $.ajax() method.

Step 1: Create the Yii Login Form

Start by opening the login view:

/protected/views/site/login.php

The following example enables client-side validation and uses the afterValidate callback to submit the form through AJAX after validation succeeds.

<?php
/* @var $this SiteController */
/* @var $model LoginForm */
/* @var $form CActiveForm */
$this->pageTitle = Yii::app()->name . ' - Login';
$this->breadcrumbs = array(
    'Login',
);
?>
<h1>Login</h1>
<p>
    Please fill out the following form with your login credentials:</p>
<div class="form"><?php
$form = $this->beginWidget('CActiveForm', array(
    'id' => 'login-form',
    'enableClientValidation' => true,
    'clientOptions' => array(
        'validateOnSubmit' => true,
        'afterValidate' => 'js:function(form, data, hasError) {
            if (!hasError) {
                var str = $("#login-form").serialize()
                    + "&ajax=login-form";
                $.ajax({
                    type: "POST",
                    url: "' . Yii::app()->createUrl('site/login') . '",
                    data: str,
                    dataType: "json",
                    beforeSend: function() {
                        $("#login").attr("disabled", true);
                    },
                    success: function(data, status) {
                        if (data.authenticated) {
                            window.location = data.redirectUrl;
                        } else {
                            $.each(data, function(key, value) {
                                var div = "#" + key + "em";
                                $(div).text(value);
                                $(div).show();
                            });
                            $("#login").attr("disabled", false);
                        }
                    },
                    error: function() {
                        $("#login").attr("disabled", false);
                    }
                });
                return false;
            }
        }'
    ),
)
);
?>
<p class="note">
    Fields with <span class="required">
</span> are required.</p>
<div class="row">
    <?php echo $form->labelEx($model, 'username'); ?>
    <?php echo $form->textField($model, 'username'); ?>
    <?php echo $form->error($model, 'username'); ?>
</div>
<div class="row">
    <?php echo $form->labelEx($model, 'password'); ?>
    <?php echo $form->passwordField($model, 'password'); ?>
    <?php echo $form->error($model, 'password'); ?>
</div>
<div class="row rememberMe">
    <?php echo $form->checkBox($model, 'rememberMe'); ?>
    <?php echo $form->label($model, 'rememberMe'); ?>
    <?php echo $form->error($model, 'rememberMe'); ?>
</div>
<div class="row buttons">
    <?php
    echo CHtml::submitButton(
        'Login',
        array('id' => 'login')
    );
    ?>
</div><?php $this->endWidget(); ?>
</div>
<!-- form -->

How the AJAX Login Form Works

The important part of this implementation is the afterValidate callback. Yii executes this callback after the form validation process finishes.

The hasError parameter tells us whether the form contains validation errors. We only send the AJAX request when hasError is false:

if (!hasError) {    // Submit the form through AJAX}

We then serialize the form fields using jQuery:

var str = $("#login-form").serialize();

The serialized data is sent to the same Yii login action with an additional ajax=login-form parameter:

var str = $("#login-form").serialize()    + "&ajax=login-form";

This parameter allows the controller to distinguish an AJAX validation/login request from a normal request.

Why Return False From afterValidate?

Returning false is important because it prevents the browser from continuing with the normal form submission.

return false;

Without this, the browser could perform the standard form submission after the AJAX request, resulting in the page being refreshed.

Disable the Login Button During the Request

Another useful part of the implementation is disabling the login button while the AJAX request is being processed:

beforeSend: function() {    $("#login").attr("disabled", true);}

After the server responds, the button can be enabled again if authentication fails:

$("#login").attr("disabled", false);

This helps prevent users from accidentally submitting the login form multiple times.

Step 2: Handle the AJAX Login Request in Yii

Now we need to handle the AJAX request in the Yii controller. Open:

/protected/controllers/SiteController.php

Add or update the actionLogin() method as follows:

/**
 * Displays the login page
 */
public function actionLogin(){
    $model = new LoginForm;
    // AJAX validation request
    if (isset($_POST['ajax'])
        && $_POST['ajax'] === 'login-form'
    )
    {
        $errors = CActiveForm::validate($model);
        if ($errors != '[]')
        {
            echo $errors;
            Yii::app()->end();
        }
    }
    // Collect user input
    if (isset($_POST['LoginForm']))
    {
        $model->attributes = $_POST['LoginForm'];
        // Validate credentials and authenticate the user
        if ($model->validate() && $model->login())
        {
            if (isset($_POST['ajax'])
                && $_POST['ajax'] === 'login-form'
            )
            {
                echo CJSON::encode(array(
                    'authenticated' => true,
                    'redirectUrl' => Yii::app()->user->returnUrl,
                    'param' => 'Any additional param'
                )
                );
                Yii::app()->end();
            }
            $this->redirect(
                Yii::app()->user->returnUrl
            );
        }
    }
    // Display the login form
    $this->render('login', array(
        'model' => $model
    )
    );
}

Understanding the Controller Logic

The controller performs two important jobs: validation and authentication.

1. Detect the AJAX Request

First, the controller checks whether the request contains the expected AJAX parameter:

if (isset($_POST['ajax'])    && $_POST['ajax'] === 'login-form'){    // Handle AJAX validation}

This lets the controller identify requests coming from the login form's AJAX workflow.

2. Validate the Form

Yii's CActiveForm::validate() method validates the model and returns the validation response:

$errors = CActiveForm::validate($model);

If validation errors exist, the response is returned immediately and the request ends:

if ($errors != '[]'){    echo $errors;    Yii::app()->end();}

This prevents the login logic from running when the submitted data does not pass validation.

3. Load the Submitted Login Data

Once the request contains the LoginForm data, the submitted attributes are assigned to the model:

if (isset($_POST['LoginForm'])){    $model->attributes = $_POST['LoginForm'];}

4. Authenticate the User

The model is then validated and the login method is called:

if ($model->validate() && $model->login()){    // Authentication successful}

If authentication succeeds, the controller returns a JSON response containing an authentication flag and redirect URL.

Returning a JSON Response

The AJAX request expects a JSON response because the JavaScript specifies:

dataType: "json"

Therefore, the Yii controller returns JSON using CJSON::encode():

echo CJSON::encode(array(    'authenticated' => true,    'redirectUrl' => Yii::app()->user->returnUrl));

The browser can then inspect the authenticated property:

if (data.authenticated) {    window.location = data.redirectUrl;}

This redirects the user after successful authentication without requiring the login form itself to perform a traditional page submission.

Displaying Login Errors

If authentication fails, the server can return validation information in the JSON response. The JavaScript loops through the returned values:

$.each(data, function(key, value) {    var div = "#" + key + "em";    $(div).text(value);    $(div).show();});

This allows the response to be displayed next to the relevant form field.

AJAX Validation vs AJAX Form Submission in Yii

It is useful to distinguish between AJAX validation and AJAX form submission.

  • AJAX validation checks submitted values and returns validation errors without performing the normal form submission.
  • AJAX form submission sends the validated form data to the server asynchronously and processes the server response with JavaScript.

Yii supports AJAX-oriented form validation, while the example above adds custom JavaScript to control the actual login submission and response handling. Yii's documentation for its ActiveForm system similarly demonstrates intercepting a validated form submission and sending the serialized data through AJAX.

Complete Yii AJAX Login Flow

The complete process can be summarized as:

  1. User submits the Yii login form.
  2. CActiveForm runs client-side validation.
  3. afterValidate checks whether validation errors exist.
  4. The default form submission is stopped.
  5. jQuery serializes the form data.
  6. An AJAX POST request is sent to site/login.
  7. Yii receives and validates the submitted credentials.
  8. The login model attempts authentication.
  9. The controller returns JSON.
  10. JavaScript redirects authenticated users or displays errors.

Things to Consider Before Using This Approach

Although AJAX can improve the login experience, the server must remain responsible for authentication and security. Client-side validation should never be treated as a replacement for server-side validation.

You should also make sure that your application uses appropriate session handling, password verification, CSRF protection, HTTPS, and Yii's normal authentication mechanisms. Never rely on JavaScript alone to determine whether a user is authenticated.

Conclusion

Creating an AJAX-based login form in Yii 1.1 is straightforward once you separate validation from form submission. CActiveForm can handle the validation stage, while jQuery's $.ajax() method can submit the validated credentials asynchronously.

The key idea is to use the validation callback to stop the browser's normal form submission, serialize the login form, send it to the Yii controller, and process the JSON response. This approach gives you a more interactive login experience while keeping authentication logic on the server.

Frequently Asked Questions

Can I submit a Yii 1.1 form using AJAX?

Yes. You can intercept the form submission after validation and use jQuery AJAX to send the form data to a Yii controller action.

What is CActiveForm in Yii?

CActiveForm is the Yii 1.1 form widget used to generate forms and integrate model-based validation and error handling.

What does afterValidate do in Yii?

The afterValidate callback is executed after the form validation process. It can be used to determine whether the form contains errors before continuing with a custom submission process.

How do I prevent a Yii form from refreshing the page?

You can prevent the normal submission by returning false from the JavaScript submission callback and sending the form data through an AJAX request instead.

Why should an AJAX login request return JSON?

JSON provides a structured response that JavaScript can inspect. For example, the server can return an authentication status, redirect URL, or validation errors.

Does AJAX validation replace server-side validation?

No. Client-side or AJAX validation improves the user experience, but authentication and validation must still be enforced on the server.

Last updated:

Work with Scriptbaker

Let's talk about your project

Whether you're extending an existing platform, modernising legacy code, or planning something new, our engineers can help. Tell us what you're working on and we'll explore a practical technical solution together.