Ajax Button In Cform

<Scenario>: In wizard steps, sometimes if the value is not in drop down list, then you need add a new items into drop down list, but you don’t want to quit current wizard. One case here is I want create a new employee account by wizard (I am using WizardBehavior, if you want to know more about WizardBehavior, search this in the community), but the employee’s type is not in my drop down list. I need add a new type for this employee, most user don’t like to quit current wizard, even we provided function to save as a draft. So I think about how to use Ajax to allow the user enter the new employee type while not quit current wizard.

<Method>:We need create an Ajax button, if the type value is not listed, then pop up a dialog window, while the user can entered new type value, and update drop down list, so the new value is available in the type list. All these operations will not harm current wizard data.

<Solution>:Step 1 - Create Ajax button in CForm. CForm is called in one of wizard step.




$return=new CForm(array(

	'showErrorSummary'=>true,

	'elements'=>array(

		'employeeType'=>array(

			'type'=>'dropdownlist',

			'items'=>array_merge(array('--select--'),CHtml::listData(Type::model()->findAll(), 'type_id', 'type_name')),

			'hint'=>'Pick up an employee type from the list.',

			//This is for depends fields, need set return=>true	

			'ajax'=>array(

				'type'=>'POST',

				'url'=>Yii::app()->createUrl('project/dynamiccus'),

				'update'=>'#ProjectInfo_projectCu', //selector to update

				//'data'=>'js:javascript statement',

			),

			'return'=>true,					

		),

		...

	),

	'buttons'=>array(

		'new_type'=>array(

			'type'=>'button',

			'label'=>'If the employee type is not found above, you can create a new one.',

			'attributes'=>array(

				'id'=>'showtypeDialog',

				'ajax'=>array(

					'type'=>'POST',

					'url'=>Yii::app()->createUrl('type/addnew'),

					'update'=>'#typeDialog',

					'onclick'=>'$("#typeDialog").dialog("open"); return false;',

				),		

			),

		),

		'<div id="typeDialog"></div>', //this part is allow your Ajax update this field, it's not a bug, CForm will return this part in HTML page directly. 

	),



Step 2 - Then next you need create new action in TypeController, make sure "addnew" is added into AccessRules, so it can be executed. Addnew function is like create, but you need call popup dialog.




	public function accessRules()

	{

		return array(

			...

			array('allow', // allow authenticated user to perform 'addnew' actions

				'actions'=>array('index','view','addnew'),

				'users'=>array('@'),

			),

			...

		);

	}

...

	/**

	 * Creates a new type in a pop-up window.

	 * If creation is successful, the browser will be redirected to the parent page.

	 */

	public function actionAddNew($type_name=NULL)

	{

		$model=new Type();

	

		// Uncomment the following line if AJAX validation is needed

		$this->performAjaxValidation($model);

	

		if(!is_null($type_name))

		{

			$model->setAttribute('type_name', $type_name);

		}

	

		if(isset($_POST['Type']))

		{

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

			//check unique before save			

			if($model->save())

			{

				//if no any issue on data save, just return

				return;

			}

		}

		//pop jui dialog

		Yii::app()->clientScript->scriptMap['jquery.js'] = false;

		$this->renderPartial('popcreate',array('model'=>$model,),false,true);

	}



Then create popcreate.php under views/type folder




<?php 

$this->beginWidget('zii.widgets.jui.CJuiDialog',array(

                'id'=>'typeDialog',

                'options'=>array(

                    'title'=>Yii::t('region','Add a New Type'),

                    'autoOpen'=>true,

                    'modal'=>'true',

                    'width'=>'auto',

                    'height'=>'auto',

                ),

                ));

echo $this->renderPartial('_formdialog', array('model'=>$model)); ?>

<?php $this->endWidget('zii.widgets.jui.CJuiDialog');?>



The "_formdialog" is file copy from "_form", which was created by Gii CURD creator. But here is for popup dialog, so need change a little bit. Put _formdialog.php in same views/type folder.




<!-- first, you need add id for this part, which can be used in Ajax call in case -->

<div class="form" id="typeDialogform">


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

	'id'=>'type-form',

	'enableAjaxValidation'=>TRUE,

)); ?>

...<!-- this part is as same as your _form.php, include all your attributes fields in Type model -->

	<div class="row buttons">

		<?php echo CHtml::ajaxSubmitButton(Yii::t('Type','Add a New Type'),CHtml::normalizeUrl(array('type/addnew','render'=>false)),array('success'=>'js: function(data) {

						$("#employeeType").append(data); /*this will update employee Type dropdown list*/

						$("#typeDialog").dialog("close");

                    }'),array('id'=>'closeTypeDialog'));

		?>

	</div>

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

</div><!-- form -->



Now all code added for this function.

Hope it will give you some helps.