Book Image

Instant Building Multi-Page Forms with Yii How-to

By : Uday Sawant
Book Image

Instant Building Multi-Page Forms with Yii How-to

By: Uday Sawant

Overview of this book

Yii is a high-performance PHP framework for rapid web application development. It is well-designed, well-supported, easy to learn, and easy to maintain. Forms are the basic method used to collect information on the Internet, and in cases like user registration and payment process, there's a lot of data to be presented and the lists can get lengthy. Instant Building Multi-Page Forms with Yii is a simple and descriptive how-to that provides step-by-step recipes to help you in converting your lengthy forms into short, interactive forms. It will guide you through the inbuilt features of Yii framework to help you with this complex job. The book starts with the basics of Yii and will guide you through creating simple forms before then converting your simple forms into multi-page forms. It will use the capabilities of Yii to ease the tasks required to do this. Yii eases your work by providing options like database connectivity. We will also take a look at the automated code generation capabilities of Yii in generating forms and necessary CRUD operations, as well as looking at how to divide a single long form into multiple views with same controller/action, and then add form validations and AJAX support to the forms. We will also cover the upload process and how to customise Yii's looks.
Table of Contents (7 chapters)

AJAX forms (Advanced)


Yii provides some useful AJAX-based options to make your forms more responsive and interactive. You can set Yii forms to validate fields on change and/or on form submission. This validation is performed by an AJAX call to the server validating the input fields without refreshing the page.

In this recipe we will learn how to enable AJAX support for form validations and submissions.

Getting ready

To see this in action, we will use the simple form generated in the Creating basic forms recipe.

How to do it...

  1. Open the file /protected/views/user/_form.php.

  2. To enable AJAX-based server-side validation, change the property enableAjaxValidation to true with the following code:

    <?php $form=$this->beginWidget('CActiveForm', array(
      'id'=>'user-form',
      'enableAjaxValidation'=>true,
    )); ?>
  3. To process AJAX validation requests, add the following lines to the action created in UserController.php:

    ...
    $model=new User;
    if(isset($_POST['ajax']) && $_POST['ajax']==='user-form')
    {
      echo CActiveForm::validate($model);
      Yii::app()->end();
    }
    if(isset($_POST['User'])) 
    ...

With this, we have enabled AJAX-based server-side validation for our form.

How it works...

When we set enableAjaxValidation to true, Yii automatically adds some JavaScript code to our form page. This code tracks the changes in the form fields and sends a request to the server to validate the changes. We can set the separate URL for validating the form data; by default, the validation requests are submitted to the action attribute of the form. In our case it is the same actionCreate attribute that is used to render the form.

In actionCreate, we have added some code to check for AJAX validation requests. If we receive an AJAX request, we simply call the CActiveForm::validate($model) method to validate the data. This method returns the validation results in JSON form, which is then passed to the client browser.

If the respective fields are valid, they will be marked with CSS for denoting class success (green color by default); else, it gets marked with red color for class error and the error description is displayed below the respective field as well as in the error-summary section.

The problem with enableAjaxValidation is that it sends validation requests for changes in any of the form fields, by default. This creates lot of traffic on the server.

To reduce server traffic with AJAX requests, add the following lines to the form definition:

<?php $form=$this->beginWidget('CActiveForm', array(
  'id'=>'user-form',
  'enableAjaxValidation'=>true,
  'clientOptions'=>array(
    'validateOnSubmit'=>true,
    'validateOnChange'=>false,
  ),
)); ?>

With this line, we have disabled the validation requests on field-change events and enabled AJAX-based validations on submitting the form. This avoids the individual validation requests and sends a single request before final submission of the form. If this request fails, the form submission is cancelled with the error description added to the form. After successful validation, a regular POST request is sent to the server submitting the form.

With this additional code, you get complete AJAX-based form submission:

<?php $form=$this->beginWidget('CActiveForm', array(
  'id'=>'user-form',
  'enableAjaxValidation'=>true,
  'clientOptions'=>array(
    'validateOnSubmit'=>true,
    'validateOnChange'=>false,
    'afterValidate'=>'js:submitForm', //JS function
  ),
)); ?>

Add the following HTML code to _form.php. This will hold the result of form submission.

<span id="result"></span>

Add the following JavaScript to _form.php under protected/views/user:

<script type="text/javascript">
function submitForm (form, data, hasError){
  //check for validation errors
  if (!hasError){
    var url = form.attr('action');
    $.post(url, form.serialize(), function(res){
      $('#result').html(res);
    });
  }
  // return false to avoid traditional form submit
  return false;
}
</script>

Set some additional code in the actionCreate method of UserController, as follows:

if(isset($_POST['ajax']) && $_POST['ajax']==='user-form')
{
  echo CActiveForm::validate($model);
  Yii::app()->end();
}

if(Yii::app()->request->isAjaxRequest)
{
  //do stuff like validate or save model
  //and set message accordingly
  echo 'Registration successful!!';
  Yii::app()->end();
}

What we did is set the forms afterValidate to submit AJAX request to actionCreate(). As we are not setting $_POST['ajax'], we track this event with Yii::app()->request->isAjaxRequest. If it's an AJAX request, simply save the model and return the success message. This is then displayed in the span tag on the form page.

Notice that we have set the submitForm function to always return false to avoid the traditional non-AJAX form submission.

There's more...

Additionally, Yii provides three static methods.

  • CHTML::ajaxLink()

  • CHTML::ajaxButton()

  • CHTML::ajaxSubmitButton()

These methods automatically create the respective HTML elements and additionally add the jQuery code for AJAX-based requests/response handling.

The following lines demonstrate the use of AJAX using these helpers:

echo CHtml::ajaxLink(
  'Submit',
  array('user/view', 'id' => $id), // Yii URL
  array('update' => '#result') // jQuery selector
);

This will create an HTML link element with the name Submit. On clicking this link, a request is posted to actionView of UserController. The first parameter provides a name or text to be used for the link. The second parameter specifies its target or href attribute. The third parameter specifies the AJAX option update that is set to replace the contents of the HTML element #result.

You can process the response data on the client script with following callback function:

echo CHtml::ajaxLink(
  'Submit',
  array('user/view', 'id' => $id),
  array(
    'dataType'=>'json',
    'success' => 'js:function(data){
      console.log(data);
      alert(data.msg); //message element in response
    }'), 
);

You can find more information on AJAX forms at the following links: