Problem With Ajax Submit Button

Hello

Yii 1.1.14

I’m trying to make a popup to select a year and then get some reporting output for the selected year :

The popup is generated by CJuiDialog. Inside CJuiDialog’, I have a form.

In the first time I had a normal submit button on the form and it worked fine.

But it did not close the popup.

Then I found this post : Yii - CJuiDialog Close on submit button click

The button of the dialog to submit the form closes the dialog but seems not to post to the indicated url.

I also tried ajaxSubmitButton() directly in the form.

Same result : Nothing happens when I click on the button.

There are no JS errors, nothing in the application log.

This is my View :




<div class="reporting">

	<?php 

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

			'id'=>'mydialog',

			'options'=>array(

				'title'=>'select year test',

				'autoOpen'=>false,

				'modal'=>true,

				'buttons' => array(

					'Dialog Submit Button'=>'js:function(){

						$.post(

							$("#select-year-form").attr("action"),

							$("#select-year-form").serialize(),

							function(){$("#mydialog").dialog("close");}						

						);

					}',				

					array('text'=>Yii::t('app','reporting.select.close'),'click'=> 'js:function(){$(this).dialog("close");}'),

				),

			),

		));

	?>

	<div class="well">

		<?php echo CHtml::beginForm(CHtml::normalizeUrl(array('/site/about')),'post',array('id'=>'select-year-form')); ?>

		<table class="contentheader">

			<tr>

			<td><?php echo CHtml::DropDownList('year', $lastyear, $yearslist, array('options'=>array($lastyear=>array('selected'=>true)) )); ?></td>

			</tr>

		</table>

		<br />

		<?php echo CHtml::ajaxSubmitButton('Form Ajax Submit Button',

				CHtml::normalizeUrl(array('/site/about')), 

				array('success'=>'function(){$("#mydialog").dialog("close");}'),

				array('name' => 'run', 'class' => 'btn btn-success')

		); ?>

		<?php echo CHtml::endForm(); ?>

	</div>


	<?php 

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

		echo CHtml::link(Yii::t('app','app.menu.reporting.planning.xlsabsence'), '#', array(

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

		));

	?>

</div>



It would be nice if someone could help me find out what the problem is !

Hi,

just try to add js: in your success method

array(‘success’=>'js: function(data) {

});

Hello - Thanks

But Sorry : I don’t get it what you want me to try - I don’t know what to put into the function {}

I am not an ajax specialist so I’m not sure if I should go in this direction.

In an ideal world I would like to get this process :

  1. open the popup

  2. select a year

  3. submit calls the action to generate a pdf file (a reporting for the year selected)

  4. This pdf generation is quite long so it would be nice to have some kind of "loading" gif image

  5. When the pdf file is generated close popup and show a flash message to tell the user that the pdf has been generated successfully.

My problem seems to be that I can’t call the pdf generation via ajax !?

So if someone can give me some hints to how come close to this scenario would be nice :)

Hi,

I wrote almost everything… its should work as u expected… if not tell me…

you are not ajax specialist. but u r using ajax…please understand ur code…

Code for this





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


	'id'=>'mydialog',

	'options'=>array(

		'title'=>'Warning!',

		'autoOpen'=>true,

		'modal'=>'true',

		'width'=>'auto',

		'height'=>'auto',

		'open' => 'js:function(event, ui) {

		}',

		'close' => 'js:function(event, ui) {

			$(".ui-dialog:has(#mydialog')").empty().remove();

		}',

)); 


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

	'id'=>'select-year-form',

	'enableAjaxValidation'=>false,

	'action'=> $this->createUrl('/site/about')),

));


                <table class="contentheader">

                        <tr>

                        <td><?php echo $form->dropDownList('year', $lastyear, $yearslist, array('options'=>array($lastyear=>array('selected'=>true)) )); ?></td>

                        </tr>

                </table>

                <br />

                <?php echo CHtml::ajaxSubmitButton('Form Ajax Submit Button',

                                CHtml::normalizeUrl(array('/site/about')),               [b]3)submit calls the action to generate a pdf file (a reporting for the year selected)[/b]

                                array(

					'type'=>'POST',


					'beforeSend' => "function(request) {

						// load your image here               [b] 4) This pdf generation is quite long so it would be nice to have some kind of "loading" gif image[/b]

			         }",

					'data' => '$("#select-year-form").serialize()',   [b]2) select a year (this will post your data to controller)[/b]

					'success'=>'function(){

						$("#mydialog").dialog("close");              [b]5) When the pdf file is generated close popup[/b]

					}',


					'complete' => "function(request) {

						// remove your image here

			         }",


			         'error' => "function(data) {

						// handle return data

						alert('erro'+data);

			         }",

				),

                                array('name' => 'run', 'class' => 'btn btn-success')

                ); ?>

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


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





echo CHtml::link(Yii::t('app','app.menu.reporting.planning.xlsabsence'), '#', array(          [b]1) open the popup[/b]

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

                ));






  1. submit calls the action to generate a pdf file (a reporting for the year selected)

Form ajax button should call your controller method

  1. This pdf generation is quite long so it would be nice to have some kind of "loading" gif image

In ajax you have to use beforesend and aftercomplete method for loading gif image

  1. When the pdf file is generated close popup and show a flash message to tell the user that the pdf has been generated successfully.

In your controller you have to set setflash method with proper message.

Hello - Thanks for all this efforts - I will work on it !

I took your code, I had to make some syntax corrections ( <?php ) " ), but then I get this message :

This line in CHtml.php is concerning activeDropDownList, where a model is needed.

I have no model, so I should use CHtml::DropDownList

You changed the code concerning the form (CActiveForm)

I there a way to use a dropdownlist without a model on a CActiveForm ?

Hi,

Yes you can use it without $form… then u have to check ur post request. whether are you getting the value on controller

if u need help come to chat on yiiframwork site… i am live…with name chandran :)

OK

Then I have an other error on the console :

Uncaught SyntaxError: Unexpected token ILLEGAL

It comes from :


$(".ui-dialog:has("#mydialog")").empty().remove();

I replaced it by :


$(".ui-dialog").empty().remove();

I also replaced the url of the ajax submit button to go the xlsAbsences action in the controller.

Now I see the popup coming up, then I click the button.

I put some alert in the beforesave and complete section and they come up but the process in xlsAbsences action (generate a file) is not done.

And when I click a second time on the button I get :

please can you try

$(".ui-dialog:has(#mydialog)").empty().remove();

i hope u r near to the solution :) cheers

you should not put any alert in ajax call… then it will halt the request…

please remove alert or replace with console.log :)

can u show me the request and response of your url

take screenshot from console

Ok I use now :


$(".ui-dialog:has(#mydialog)").empty().remove();

I also replaced alert with console.log

When I click the first time on submit button I get this on console :

The popup closes properly but as I said there is no xls file generated.

And this I get on network tab :

Here’s the request header & response on index.php?r=planning/xlsAbsences :

When I click a second time on submit button I get this on console :

Hi,

I have to mention this…

your ajax call is working perfectly :) congratz

I found two problem

[size="2"]Form Dataview sourceview URL encoded[/size]

$("#select-year-form").serialize(): // This is wrong …selected year should go

you have to remove above line from your code and use the following code

$(’#dropDownId :selected’).text(); // change according to your dropdownid

For more clearance read this link

http://stackoverflow…tmldropdownlist

That is the reason …its not generating pdf…

so still request is not perfectly build…

Content-Disposition:attachment;filename="XLS TEST (2014) 2014-02-12.xls"

how above date got append? is it hard coded ?

Hello,

Yes I removed select-year-form line.

The filename is a name + the year & date appended.

Even now no file generated and still error if clicked a second time.

Now the request header & response is this :

I better show you my sources now :

My view :




<div class="reporting">

	<?php

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

			'id'=>'mydialog',

			'options'=>array(

				'title'=>'Warning!',

				'autoOpen'=>true,

				'modal'=>'true',

				'width'=>'auto',

				'height'=>'auto',

				'open' => 'js:function(event, ui) {

				}',

				'close' => 'js:function(event, ui) {

					$(".ui-dialog:has(#mydialog)").empty().remove();

				}',

			)

		)); 


	?>

	<table class="contentheader">

		<tr>

			<td>

				<?php echo CHtml::DropDownList('dropDownId', $lastyear, $yearslist, array('options'=>array($lastyear=>array('selected'=>true)) )); ?>

			</td>

		</tr>

	</table>

	<br />

	<?php echo CHtml::ajaxSubmitButton('Form Ajax Submit Button',

				CHtml::normalizeUrl(array('/planning/xlsAbsences')), 

				array(

					'type'=>'POST',

					'beforeSend' => "function(request) { console.log('beforeSend'); }",

					'data' => '$("#dropDownId :selected").text()',

					'success'=>'function(){	$("#mydialog").dialog("close"); }',

					'complete' => "function(request) { console.log('complete'); }",

					'error' => "function(data) { alert('erro'+data); }",

				),

				array('name' => 'run', 'class' => 'btn btn-success')

	); ?>

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

		echo CHtml::link(Yii::t('app','app.menu.reporting.planning.xlsabsence'), '#', array( 

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

		));

	?>

</div>



My controler action :




public function actionXlsAbsences()

	{

		if (isset($_POST['dropDownId'])) {

			$year = $_POST['dropDownId'];

		} else {

			$year = '2014';

		}

		Yii::import('ext.phpexcel.XPHPExcel');      

		$phpExcel = XPHPExcel::createPHPExcel();	

		$objPHPExcel = new PHPExcel();

		$styletitle = $objPHPExcel->setActiveSheetIndex(0)->getStyle('A1')->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);

		$styletitle = $objPHPExcel->setActiveSheetIndex(0)->getStyle('A1');

		$styletitle->applyFromArray(array(

			'font'=>array(

				'bold'=>true,

				'size'=>14,

				'name'=>'Arial',

				'alignment' => array(

					'horizontal' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER),

				'color'=>array(

					'rgb'=>'FF00FF00'))

		));

		$objPHPExcel->setActiveSheetIndex(0)

			->duplicateStyle($styletitle,'A1:O1');

		foreach(range('A','O') as $columnID) {

			$objPHPExcel->getActiveSheet()->getColumnDimension($columnID)

				->setAutoSize(true);

		}

			

		$objPHPExcel->setActiveSheetIndex(0)

			->setCellValue('A1', $year);

		$objPHPExcel->getActiveSheet()->setTitle('Test');

		$objPHPExcel->setActiveSheetIndex(0);

		$filename = 'XLS TEST ('.$year.') '.date('Y-m-d');

		header('Content-Type: application/vnd.ms-excel');

		header('Content-Disposition: attachment;filename="'.$filename.'.xls"');

		header('Cache-Control: max-age=0');


		$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');


		$objWriter->save('php://output');

		unset($this->objWriter);

		unset($this->objWorksheet);

		unset($this->objReader);

		unset($this->objPHPExcel);

	}



[size=2]view change[/size]

‘data’=>‘js:$("#select-year-form").serialize()+"&year="+$("#dropDownId :selected").text()’,

controller change

if (isset($_POST[‘year’])) {

                    &#036;year = &#036;_POST['year'];


            } else {


                    &#036;year = '2014';


            }

in request you should not see this javascript code… you should see the year… then your request is right or else its still wrong…

Form Dataview sourceview URL encoded

$("#dropDownId :selected").text():

You have one more chance to try… :) cheers

you can ask me again only once :(

Ok I understand …

I get the year now :

Still no xls file generated but I can see that xlsAbsences has the xls data in response :

I read a lot of posts about downloading the returned data as a file - there seem to be two ways : iframe and form

I think in a first time I will work on a form solution - So I keep my last option in case I have some trouble to get it work :)

But in any case great thanks for your help !

Congratz for your success :) nice to help you

I read a lot of posts (as this one), so I updated my script to download automatically the generated Excel file, that I found in the request response.

The process works as I want : the hidden form is submitted automatically and a file with the right name and extension (xls) is downloaded.

But this file can’t be opened by Excel (it says that the format of the file is different of format specified by the extension.

This is the code for success in the view :




'success'=>'function(response, status, request){	

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

	var disp = request.getResponseHeader("Content-Disposition");

	if (disp && disp.search("attachment") != -1) {

		var filename = disp.substring(21).replace("\"","");

		var form = $("<form method=\"POST\" action=\"index.php?r=planning/dl\">");

		form.append($("<input type=\"hidden\" name=\"content\" value=\"" + request.responseText + "\">"));

		form.append($("<input type=\"hidden\" name=\"filename\" value=\"" + filename + "\">"));

		$("body").append(form);

		form.submit();

	}

	console.log(filename);

	console.log(request.responseText);

}',



I created a new action as target for the form action - its called actionDl :




	public function actionDl()

	{

		$filename = $_POST['filename'];

		$content = $_POST['content'];

		

		header("Content-Disposition: attachment; filename=".$filename);

		header('Content-Type: application/octet-stream');

		header('Cache-Control: max-age=0');

		echo $content;

	}



I thought that request.responseText contains the content of the excel file, but perhaps I’m wrong about that ?