AjaxSubmit in CJuiDialog result headache

Hello ppl, once again i have an ajax issue.

I have a view which has an ajaxLink view/_form.php




....

	<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("test",$this->createUrl('/job/addnew'),array('onclick'=>'$("#jobDialog").dialog("open")','update'=>'#job'),array('id'=>'showJobDialog')); ?>

            </div><!--//'success'=>'function(data) {  $(data).appendTo("#job"); }'-->

                <?php echo $form->error($person,'jid'); ?>

	</div>

....

the result of this link is this actionAddnew in JobController.php




...

        public function actionAddnew() {

                $model=new Job;

                

                    


		// Uncomment the following line if AJAX validation is needed

		$this->performAjaxValidation($model);


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

		{

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

			if($model->save()) {

                            //Here where i want the CJuiDialog to close and create a dropdownlist to the main form

                        }

                               

		}

                if(!isset($_GET['render'])) {

                    $this->renderPartial('createDialog',array(

			'model'=>$model,

                    ),false,true);

                }

		


        }

...

Please notice the comment in if($model->save()) .

Now the view/createDialog.php where the CJuiDialog initiallizes





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

                'id'=>'jobDialog',

                'options'=>array(

                    'title'=>Yii::t('job','Create Job'),

                    'autoOpen'=>'true',

                    'modal'=>'true',

                ),

                ));?>


<?php 

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

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



Which rendersPartial view/_formDialog.php which is this.





<div class="wide form" id="jobDialogForm">


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

	'id'=>'job-form',

	'enableAjaxValidation'=>true,

)); ?>


	<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::submitButton($model->isNewRecord ? 'Create' : 'Save'); 

                        echo CHtml::ajaxSubmitButton(Yii::t('jib','Create Job'),CHtml::normalizeUrl(array('job/addnew','render'=>false)),array('update'=>'#job'),array(


                )); ?>

	</div>


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


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



I want when I press the create on the CJuiDialog to be able to save the model (if passed the validation) and update or replace the dropdownlist in the main _form so it contains the new entry.

Any help welcom.

I’m working on something similar. This is what I have so far:

I have a link for adding customers on the fly, using a CJuiDialog. In the dialog widget I use renderPartial and a CActiveForm just like you do.

In my case the controller returns the id of the newly inserted record. In the ‘success’ handler I test for a valid record id, update a target field in the main form and finally close the dialog. (I chose to pass the id of the target field in the data array parameter to renderPartial).




echo CHtml::ajaxSubmitButton(

  'Create',

  array('/customer/addCustomerAjax'),

  array(

    'success'=>'js:'

    .'function(id){ if (id) { '

      .'$("#'.$target_field.'").val(id);'

      .'$("#add_customer_dialog").dialog("close");'

    .'} else '

      .'alert("couldn't save")'

    .'}',

  ));



Edit: changed a selector with typo

/Tommy

can you expain how do you return the id from the controller and how do you fetch it in the main view?

Correction, the controller echoes the id.




echo $model->customer_id;



I don’t have to fetch the result in the main view since everything takes place in the same document. All I have to do is to propagate the target id to the partial view. The partial view recieves the result from the controller and updates the target accordingly, then closes the dialog. You’ll have to figure out have to use jQuery for appending the new option to your dropdownlist (if that’s what you intended to do).

Edit: clarification

/Tommy

Nice and thanks.

Firstly, i have tested to put the CJuiDialog in my main form but it does open even when i have turn


'autoOpen'=>'false',

but even it does not open i don’t want to put in the main view _form because i need more of dialogs and it will be not neccessary to load all this dialogs because use may not use them at all.

Secondly because i am newb to jquery and ajax i dont know how to fetch the "appending the new option to your dropdownlist"

And finally i used echo like you said like this


echo CHtml::ajaxSubmitButton(

  'Create',

  array('/customer/addCustomerAjax'),

  array(

    'success'=>'js:'

    .'function(id){ if (id) { '

      .'alert(id);'

      .'$("#this-dialog").dialog("close");'

    .'} else '

      .'alert("couldn't save")'

    .'}',

  ));

and the result was the full HTML code of the page in the alert.

Sorry for this post, wasn’t intentional.

Check the url you use, I think you get the default page back. The test if(id) should be improved, thanks for the pointer.

I did a mistake when editing the above ajax of the submitbutton. It was meant to be #this_dialog (don’t use a hyphen). I should have named it #add_customer_dialog instead. (Another reason for editing was that I removed a secondary ajax call from the ‘success’ function.)

Regarding the dropDownList you may want to return a html option string, ready to be inserted. If you just want to replace the current options use $("#id_of_dropdown").html(id). The identifier ‘id’ should be changed to something more suitable.

This cookbok article has an example of returning an option tag

http://www.yiiframework.com/doc/cookbook/24/

/Tommy

Ok will try it on Monday. And will feed you back. Are you intrested of writing a cookbook instruction on this issue?

Is this has to do with what i issue ?

How do I get and use the server response from an AJAX request?

Yes you are on the right track. The parameters to the Yii CHtml::ajax… functions will generate the $.ajax() call for you. For instance if you specify ‘update’ in ajaxOptions, something like ‘success’: ‘function(html){$("#id").html(html)}’ will be generated. Likewise, if you specify ‘replace’, something like ‘success’: ‘function(html){$("#id").replaceWith(html)}’ will be generated. If you specify ‘success’, that will be inserted as is.

I surely will consider writing cookbook articles when I feel more comfortable with state-of-the-art web programming. (I’m more of a general purpose programmer.)

For instance I’m not satisfied with the structure of the example in my previous posts. Although it seems very usable to be able to set off a couple of CJuidialogs for creating non-existent users, projects, <whatever> instead of leaving the main form and render a completely different form, the view tends to become very complex. My main form uses CJuiAccordion enclosing a CActiveform divided into subsets of fields which can be tabbed through, opening accordion tabs as needed. I also have CJuiAutoComplete on page, but still have to figure out how to make it live happily together with CActiveForm.

/Tommy

In conclusion, you may say that CJuiDialog has issues with CActiveForm?

I placed the CJuiDialog widgets outside of the main CJuiAccordion/CActiveForm. I don’t expect any problem moving the links that set off the dialogs into the form. The CJuiAutoComplete had some problem though. IIRC the ajax validation didn’t work. Perhaps I’ll give it another try later.

renderPartial/CActiveForm inside CJuiDialog have no issues so far.

/Tommy

solved. I will post the resutl soon. :)

No the issue i am facing is that when i submit a form in a CJuiDialog and try to open a "new" dialog for the second time, I get 2 dialogs.

This is where i use the ajax to call it.




	<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("test",$this->createUrl('/job/addnew'),array('onclick'=>'$("#jobDialog").dialog("open")','update'=>'#jobDialogDiv'),array('id'=>'showJobDialog'));//UPDATE 'update'=>'#jobDialogDiv'?>

            </div>

            <div id="jobDialogDiv"></div>


	</div>

And this is the widget.




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


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

	'id'=>'job-form',

	'enableAjaxValidation'=>true,

)); ?>


............

	<div class="row buttons">

		<?php echo CHtml::ajaxSubmitButton(Yii::t('jib','Create Job'),CHtml::normalizeUrl(array('job/addnew','render'=>false)),array('success'=>'js: function(data) {

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

                        $("#jobDialogForm").remove();

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

                        

                        

                    }'),array('id'=>'closeJobDialog')); ?>

                

	</div>


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


</div><!--  -->

By comparing document (effective) content using Firebug Console, I think you should be able to find out what’s going on. How is the dialog loaded (renderPartial)?

This is how I use it (no roundtrip to controller). CJuiDialog already in view. It only contain a renderPartial of a CActiveForm subview. This may or may not be the final design.




<?php

  echo CHtml::link('some label', '#', array(

    'onclick'=>'$("#some_dialog_id").dialog({modal:true}).dialog("open"); return false;',

  ));

?>



/Tommy

Firstly i have tried to have the CJuiDialog in main page and it opens when then site loads. But it’s not something that i want and like because i think it overloads the page with no reason?!?

& Yes i use render Partial.

This is something strange.

Screenshot

So i add it the following to my main form and the result works good (even though the data are not cleared after the first insert).

The problem is validation is not working. :S


<?php

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

                'id'=>'jobDialog',

                'options'=>array(

                    'title'=>Yii::t('job','Create Job'),

                    'autoOpen'=>false,

                    'modal'=>'true',

                ),

                ));?>


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


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

	'id'=>'job-form',

	'enableAjaxValidation'=>true,

));

$model=new Job();?>


	<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('jib','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>

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



The validations is not working because the POST is been send to the person/create instead of job/addnew. :S

Ok. Solved. Will create a cookbook soon :)

The cookbook

Thanks to both tri and tydeas_dr, this thread (and the related cookbook entry) helped me a lot :)

If you still have trouble with the autoOpen option, I think you should use


'autoOpen'=>false,

instead of


'autoOpen'=>'false',

Yes have noticed this a time ago but didn’t mention it here. Hope you found the cookbook usefull