CJuiDialog and AjaxSubmitButton

26 followers

Hello ppl. Even though i have a small experience with yii I though of writing this to help people which want to do something similar.

Scenario

We have a model Person how represent persons. The person has a Job. The user must select a job from a dropdownlist when he creates the person. What if the person's job is not listed in the dropdownlist and we don't want to redirect user to the job/create page. Here comes the CJuiDialog. We will create a CJuiDialog ( a modal one ;) and we will create a new job and the new job inserted will be also appended to the existing dropdowlist.

What we will use

1. AjaxLink:

We will use an ajaxLink which will be located to the person/views/_form.php ( we will call it _form from now on ) where we create the person. The role of this ajaxLink will be to open the CJuiDialog.

2. JobController ActionAddnew:

The ajaxLink will call an action in the JobController with name ActionAddnew ( we will call it Addnew from now on ), which will either save the job ( after validation ) either rendering the job form.

3. _FormDialog:

Finally, the job form which consist of a create.php view and a _formDialog.php view, both exist under under job/views/. The _formDialog.php ( we will call it _formDialog from now on ) will contain an ajaxSubmitButton to submit the Job we want to create.

Code and details

Now, I don't know from where exactly I should start to make it easier for you. I assume you have a little experience with ajaxLink etc., though I will try to be as detailed as I can.

_form. The person's create form.

<div class="row">
.....
<?php echo $form->labelEx($person,'jid'); ?>
<div id="job">
    <?php echo $form->dropDownList($person,'jid',CHtml::listData(Job::model()->findAll(),'jid','jdescr'),array('prompt'=>'Select')); ?>
    <?php echo CHtml::ajaxLink(Yii::t('job','Create Job'),$this->createUrl('job/addnew'),array(
        'onclick'=>'$("#jobDialog").dialog("open"); return false;',
        'update'=>'#jobDialog'
        ),array('id'=>'showJobDialog'));?>
    <div id="jobDialog"></div>
</div>
.....
</div>
Where to pay attention:
  1. dropDownList

    $attribute set to 'jid'

  2. ajaxLink

    $url calls the ActionAddnew in JobController.php

    $ajaxOptions has to do with #jobDialog the div after the ajaxLink which will contain the CJuiDialog after the 'update'

    and finally last but not least the $htmlOption where I set an id to the ajaxLink for avoiding some issues.

JobController. The ActionAddnew.

public function actionAddnew() {
                $model=new Job;
        // Ajax Validation enabled
        $this->performAjaxValidation($model);
        // Flag to know if we will render the form or try to add 
        // new jon.
                $flag=true;
        if(isset($_POST['Job']))
        {       $flag=false;
            $model->attributes=$_POST['Job'];
 
            if($model->save()) {
                //Return an <option> and select it
                            echo CHtml::tag('option',array (
                                'value'=>$model->jid,
                                'selected'=>true
                            ),CHtml::encode($model->jdescr),true);
                        }
                }
                if($flag) {
                    Yii::app()->clientScript->scriptMap['jquery.js'] = false;
                    $this->renderPartial('createDialog',array('model'=>$model,),false,true);
                }
        }

Where to pay attention:

The scriptMap parameter is essential. Without that line, jquery.js will be loaded again and can cause issues with javascript both already existing on the page, as well as duplicated event handlers for ajax calls run multiple times that contain their own javascript. You may want to use scriptMap to prevent other js files from loading again using '*.js' as the array key.

I think the rest is straightforward. Pay attention the last 2 parameters of renderPartial We call first the createDialog.php from job/views/ which is the following.

createDialog.php

<?php 
$this->beginWidget('zii.widgets.jui.CJuiDialog',array(
                'id'=>'jobDialog',
                'options'=>array(
                    'title'=>Yii::t('job','Create Job'),
                    'autoOpen'=>true,
                    'modal'=>'true',
                    'width'=>'auto',
                    'height'=>'auto',
                ),
                ));
echo $this->renderPartial('_formDialog', array('model'=>$model)); ?>
<?php $this->endWidget('zii.widgets.jui.CJuiDialog');?>

Where to pay attention:

The 'id'=>'jobDialog', and step back to the _form "pay attention." :) Here we initialize the CJuiDialog widget and we render the _formDialog.php

_formDialog

<div class="form" id="jobDialogForm">
 
<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'job-form',
    'enableAjaxValidation'=>true,
)); 
//I have enableAjaxValidation set to true so i can validate on the fly the
?>
 
    <p class="note">Fields with <span class="required">*</span> are required.</p>
 
    <?php echo $form->errorSummary($model); ?>
 
    <div class="row">
        <?php echo $form->labelEx($model,'jid'); ?>
        <?php echo $form->textField($model,'jid',array('size'=>60,'maxlength'=>90)); ?>
        <?php echo $form->error($model,'jid'); ?>
    </div>
 
    <div class="row">
        <?php echo $form->labelEx($model,'jdescr'); ?>
        <?php echo $form->textField($model,'jdescr',array('size'=>60,'maxlength'=>180)); ?>
        <?php echo $form->error($model,'jdescr'); ?>
    </div>
 
    <div class="row buttons">
        <?php echo CHtml::ajaxSubmitButton(Yii::t('job','Create Job'),CHtml::normalizeUrl(array('job/addnew','render'=>false)),array('success'=>'js: function(data) {
                        $("#Person_jid").append(data);
                        $("#jobDialog").dialog("close");
                    }'),array('id'=>'closeJobDialog')); ?>
    </div>
 
<?php $this->endWidget(); ?>
 
</div>

Where to pay attention:

  1. In the 'success' js function the data is the what the ActioAddnew echoes.

$("#Person_jid").append(data); This append the data to the 'jid' dropDownList ( check _form ).

  1. $("#jobDialog").dialog("close"); We close the dialog.

  2. array('id'=>'closeJobDialog') We give unique id for this ajaxLink to avoid issues as we said before.

Total 11 comments

#6849 report it
ben1978 at 2012/02/09 04:45am
gr8

The scriptMap parameter is essential. Without that line, jquery.js will be loaded again and can cause issues with javascript both already existing on the page, as well as duplicated event handlers for ajax calls run multiple times that contain their own javascript. You may want to use scriptMap to prevent other js files from loading again using '*.js' as the array key.

it helps! thanks a lot

#6474 report it
Nicolas400 at 2012/01/12 11:11am
Stay in form after Errors

Hi, i having problems with the validation, I colud see errors on fields wher I lost focus on them, but when I click submit button, the form closes and no add data to the select.

so i change this line in my addnew action:

if($model->save()) {
                //Return an <option> and select it
                            echo CHtml::tag('option',array (
                                'value'=>$model->id,
                                'selected'=>true
                            ),CHtml::encode($model->apellido),true);
            } else {
                $flag=true;
            }
 
 
I added _else_ to let the function show again the form ...
 
Let me know if there is another way.
Best Regards
#5821 report it
sirin_ibin at 2011/11/16 10:20am
i got this working

i got this working by using the below code.

the code for ajaxLink:Here i have used the success event instead of update and it worked.

echo CHtml::ajaxLink(Yii::t('job','ADD NEW LOCATION'),$this->createUrl('location/create'),array(
        'success'=>'js:function(data){
  $("#jobDialog").dialog("open");
  document.getElementById("update_div").innerHTML=data;   
}
',     
        ),array('id'=>'showJobDialog',
 
 
       ));

now the update div(ie the div we are going to upadate with the jquiry dialog which contains the form.). here i have placed the update div inside of jquiry dialog widget(Note:AutoOpen=false).

<?php 
 
$this->beginWidget('zii.widgets.jui.CJuiDialog',array(
                'id'=>'jobDialog',
                'options'=>array(
                    'title'=>Yii::t('job','Create Job'),
                    'autoOpen'=>false,
                    'modal'=>'true',
                    'width'=>'auto',
                    'height'=>'auto',
                ),
                ));
 
?>
 <div id="update_div"></div>
 
<?php
 
 $this->endWidget('zii.widgets.jui.CJuiDialog');
?>

Note:please dont place this widget inside create.php .

Regards, sirin k http://www.sirink.tumblr.com

#5820 report it
sirin_ibin at 2011/11/16 09:47am
Jquiry Dialogbox is not loading.

i tried this example but for me it loads the form without any dialog to the update div. One more thing i want to point out about the above exmpale is that there is no "onclick" event in the ajaxOptions of an ajaxLink and it can be placed inside "htmlOptions" ie the 4'th argument as an array but if we are placing an onclick event in "htmlOptions" in the above example it wont load the remote content to the update div.

Regards, sirin k http://www.sirink.tumblr.com

#5626 report it
nettrinity at 2011/10/26 10:13am
couldn't understand about this code

Why here 'render' => false?

CHtml::normalizeUrl(array('job/addnew','render'=>false))
#5624 report it
nettrinity at 2011/10/26 09:55am
Question
<?php echo CHtml::ajaxSubmitButton(Yii::t('job','Create Job'),CHtml::normalizeUrl(array('job/addnew','render'=>false)),array('success'=>'js: function(data) {
                        $("#Person_jid").append(data);
                        $("#jobDialog").dialog("close");
                    }'),array('id'=>'closeJobDialog')); ?>

What is this code doing? I couldn't understand it. Please help! Thank you!

$("#Person_jid").append(data);
                        $("#jobDialog").dialog("close");
#5263 report it
DiegoToala at 2011/09/27 05:27pm
Error in Controller

Hello all, I was following the tutorial, everything was ok but the code didn't work.

I noticed that have to add the actionAddNew to the accessRules in the JobController.

If one has the same problem here is the solution, just add the acction to the access Rules.

Regards, Diego

public function accessRules()
    {
        return array(
            array('allow',  // allow all users to perform 'index' and 'view' actions
                'actions'=>array('index','view','addnew'),
                'users'=>array('*'),
            ),
#4634 report it
phazei at 2011/07/28 02:21am
onclick?

First of all, great tutorial, really useful.

I'm a bit unclear on the "onclick" part. It's in the ajaxOptions array, but it's not an ajax option nor is it one of the extras Yii added for convenience like the "update". Perhaps at the time this tutorial was written either Yii or jQuery has a slightly different API. It could be moved to the next array, and act as the onclick for the ajaxLink, but then it tries to open a blank modal and returns so never completes the ajax request the first time.

Whenever the ajaxLink is clicked it reloads the request which also causes the script to download jquery.js, jquery-ui.min.js, and the css file all over again which is a lot for every click. Seems the "onclick" would be best placed in the htmlOptions something like:

'onclick'=>'if (jobAjaxComplete) { $("#jobDialog").dialog("open"); return false; } else { jobAjaxComplete = true; }',

Where jobAjaxComplete is global. So after the first request it simply opens the already created modal rather than getting it again.

#3610 report it
nettrinity at 2011/04/22 10:52am
What is the class of $form?

what is the class of $form here? <?php echo $form->labelEx($person,'jid'); ?>

#3095 report it
anandhi at 2011/03/15 06:37pm
Multiple ajax submission If you have submit button on Dialog

/*This will fix multiple ajax submittion problem */

$this->beginWidget('zii.widgets.jui.CJuiDialog',array( 'id'=>"dmaDialog", 'options'=>array( 'closeOnEscape'=>true, 'title'=>Yii::t("dma",'CREATE DMA'), 'autoOpen'=>true, 'modal'=>'true', 'width'=>'450px', 'height'=>'auto', 'resizable' =>false, 'close'=>"js:function(e,ui){

/* Use the below undelegate function to destroy JQuery event. Otherwise when you open dialog 1st time, It will do ajax submission 1 time, if you open 2end time, It will submit 2 times etc.. You could see the ajax submission in firebug */ jQuery('body').undelegate('#closeDmaDialog', 'click');

                    jQuery('#dmaDialog').empty();
                 }",
            ),
            ));
#2855 report it
zaccaria at 2011/02/17 06:33am
other approach

See also this tutorial, that uses the onSubmit event instead of ajaxSubmit button.

Leave a comment

Please to leave your comment.

Write new article
  • Written by: tydeas_dr
  • Updated by: phazei
  • Category: Tutorials
  • Votes: +24 / -1
  • Viewed: 24,414 times
  • Created on: May 11, 2010
  • Last updated: Jul 28, 2011
  • Tags: AJAX