Yii 1.1: CJuiDialog and AjaxSubmitButton

51 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 20 comments

#17682 report it
andrew80 at 2014/07/14 08:35am
#Person_jid

views/person/_form.php

<?php echo $form->dropDownList($person,'jid',CHtml::listData(Job::model()->findAll(),'jid','jdescr'),array('prompt'=>'Select')); ?>

This line generates

<select id="Person_jid" name="Person[jid]">
<option...
...
</select>

Attention at id="Person_jid"!

views/job/_formDialog

$("#Person_jid").append(data);

This code adds a new option-line (answer from controllers/JobController) in the <select id="Person_jid" name="Person[jid]">

#16701 report it
lgastmans at 2014/03/21 02:56am
double post clicking on form

When the dialog opens, and I click in the white space of the form, a POST is executed in Firebug, and then when I click the submit button another POST is executed which creates a double entry in the db.

Anyone else have this problem, solved this problem?

#15662 report it
Selvakumar at 2013/12/05 04:57am
Update Content With Ajax And Ajax Auto Refresh Div
#15325 report it
Lukatone at 2013/10/29 12:11am
Multiple submission

I´m having a problem when submitting multiple times. I´d follow the steps of anandhi but couldn't solve it yet. Has anyone else the same issue? Excellent tutorial!

#11829 report it
lagogz at 2013/02/06 10:27am
Dropdownlist doesn't refresh!!!

$model-save() save my data into database table, but it returns FALSE!!!!!

What happen???

EDIT!!!

I disabled ajaxValidation and it works!

Thanks for the article.

#10799 report it
Jimlam at 2012/11/24 03:09pm
Datepickers in my form no longer work when I use this code

This wiki is great: I have used this code and it works fine but the only problem is that I have 2 datepickers on my form (CJuiDatePickers) and they do not work each time I use the code to create a new client. When I do not use the code (that is, client exists already) the datepickers work fine. Can anyone suggest what I should do. I tried to reactivate the datepickers by using afterajaxupdate but it works only intermittently.

#9894 report it
olivier at 2012/09/19 10:31am
reply to WebDevPT

Hello, I've used this and I believe

$("#Person_jid").append(data);

is used to append the newly created item to the dropdownlist.

Person_jid is the html id for the dropdownlist in you r_form.php

I hope that I don't say a stupid thing and that I help you.

I am sorry I can not reply to the rest of your question.

AGAIN I need to remove AJAXVALIDATION for this to work. anyone knows why ? best regards.

#9893 report it
WebDevPT at 2012/09/19 09:57am
What if we have 2 forms requiring the same cjuidialog? Is this possible?

Also what is this doing exactly?

$("#Person_jid").append(data);

Do I need to use exacly "ModelA_FieldNameInModelA" in order for this to work?

I would like to have 2 Models containing the same add new for a specific field, for example Cities for Persons and for Companies. What would be a good way to implement this?

#9632 report it
olivier at 2012/08/30 04:44pm
error ["jdesc cannot be blank."]}

I have this error message that appears in the div "jobDialog" {"Job_jdesc":["jdesc cannot be blank."]} and the dialog does not open.

UPDATE: The error disappears and the dialog opens if I remove $this->performAjaxValidation($model); from the actionAddnew in the job controller... but then the new record is done in database but not added to the dropdownlist. I have to refresh the page...

any help ? thxs.

#9531 report it
bluezed at 2012/08/21 02:35am
Great!

Thanks so much for this line:

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

I've been trying to figure out why my CJuiDialog won't come up when another Ajax button was clicked first... Have been trying to figure it out for hours so this just made my day!

Thanks a lot :)

#9298 report it
Waleed Hassan at 2012/08/02 08:47am
Good Job

I'm following the tutorial step by step, and the dialog is shows up, but submit button did not save the new entry and did not shows into the drop down list.

any one have a solution for me.

#7626 report it
w00tw00t111 at 2012/04/03 04:52pm
Check Your Rules

If you are unable to view your modal/form/add data make sure that you have added the action to your accessRules and granted yourself sufficient permission to access this action.

Example is below:

public function accessRules()
{ .......
array('allow', // allow authenticated user to perform 'create' and 'update' actions
    'actions'=>array('create','update','admin','delete','AddNew'),
    'users'=>array('@'),
),
......
}
#7625 report it
w00tw00t111 at 2012/04/03 04:49pm
Additional ScriptMap Issues

To all those that may still have problems:

What happened on mine is after the dialog came up successfully Chrome would throw a TypeError when I submitted the data. I found the conflict was NOT with jquery.js but infact was jquery.min.js.

I added the following in the controller /addnew

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

This is an excellent write up, thank you for such a complete tutorial! Hope this helps save someone else time, too.

#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
xNicox 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
#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'); ?>

Leave a comment

Please to leave your comment.

Write new article
  • Written by: tydeas_dr
  • Updated by: phazei
  • Category: Tutorials
  • Yii Version: 1.1
  • Votes: +37 / -2
  • Viewed: 83,242 times
  • Created on: May 11, 2010
  • Last updated: Jul 28, 2011
  • Tags: AJAX