CJuiDialog to create new model

  1. Introduction
  2. Scenario
  3. Preparation of the form
  4. Enhance the action create
  5. The dialog
  6. Summary

Introduction

In this tutorial we will learn how to realize a create interface using a dialog.

Here is a similar tutorial that uses Ajax link to achieve the goal, but we will use a simpler and more effective approach: the event onSubmit of the form.

Scenario

Let's imagine we have a classroom with many students. If the user fills in the form of the student and there is no classroom made, he will have to create a classroom first and lose the already inserted input.

We want to allow the user to create the classroom from the form of the student, without changing pages.

Preparation of the form

First of all we need a form for creating the classroom. We can generate a Crud for classroom with gii and adapt the code to our needs.

Once we are satisfied with our form and it works with the usual submit, we can use it in a dialog.

Enhance the action create

We need to enhance the action create of the classroom controller.

Let's change it this way:

public function actionCreate()
	{
		$model=new Classroom;

		// Uncomment the following line if AJAX validation is needed
		// $this->performAjaxValidation($model);

		if(isset($_POST['Classroom']))
		{
			$model->attributes=$_POST['Classroom'];
			if($model->save())
			{
				if (Yii::app()->request->isAjaxRequest)
				{
					echo CJSON::encode(array(
						'status'=>'success', 
						'div'=>"Classroom successfully added"
						));
					exit;				
				}
				else
					$this->redirect(array('view','id'=>$model->id));
			}
		}
		
		if (Yii::app()->request->isAjaxRequest)
		{
			echo CJSON::encode(array(
				'status'=>'failure', 
				'div'=>$this->renderPartial('_form', array('model'=>$model), true)));
			exit;				
		}
		else
			$this->render('create',array('model'=>$model,));
	}

We add some small changes: in case of ajax request we write a json encoded array.

In this array we return a status (failure/success) and the whole form created with renderPartial.

The dialog

Now the back-end is done, let's write the dialog itself.

In the form of the student somewhere we add this code:

<?php echo CHtml::link('Create classroom', "",  // the link for open the dialog
	array(
		'style'=>'cursor: pointer; text-decoration: underline;',
		'onclick'=>"{addClassroom(); $('#dialogClassroom').dialog('open');}"));?>

<?php
$this->beginWidget('zii.widgets.jui.CJuiDialog', array( // the dialog
    'id'=>'dialogClassroom',
    'options'=>array(
        'title'=>'Create classroom',
        'autoOpen'=>false,
        'modal'=>true,
		'width'=>550,
		'height'=>470,
    ),
));?>
<div class="divForForm"></div>

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

<script type="text/javascript">
// here is the magic
function addClassroom()
{
	<?php echo CHtml::ajax(array(
			'url'=>array('classroom/create'),
			'data'=> "js:$(this).serialize()",
			'type'=>'post',
			'dataType'=>'json',
			'success'=>"function(data)
			{
				if (data.status == 'failure')
				{
					$('#dialogClassroom div.divForForm').html(data.div);
                          // Here is the trick: on submit-> once again this function!
					$('#dialogClassroom div.divForForm form').submit(addClassroom);
				}
				else
				{
					$('#dialogClassroom div.divForForm').html(data.div);
					setTimeout(\"$('#dialogClassroom').dialog('close') \",3000);
				}
				
			} ",
			))?>;
	return false; 
	
}

</script>

And that's all. In this code we have:

  • A link for open the dialog
  • the dialog itself, with a div inside that will be replaced with ajax
  • the javascript function addClassroom().

This function fires an ajax request to the action create we prepared in the previous step.

The returned form will be placed in the dialog (with eventually, all errors and so on) in case of status failure, in case of status success in the example we replace the div and we close the dialog after 3 seconds.

If you use this system in the form for student, you can return, for example, the id of the newly inserted classroom and select it automatically in a drop down list.

Summary

To make a long story short:

  • Prepare the usual creation with gii generated code
  • Change the action create for answer to Ajax requests
  • Place the link/dialog/js wherever you want.

This methodology is very comfortable because it changes anything in the code of the _form, so any eventually added field in classroom will be available in both standard and dialog insert.