Reputation: 3608
I submit my forms to server via jQuery plugin AjaxForm.
This is my simplified view:
<div id="output1">...here goes my CakePHP PHP form code...</div>
<script type="text/javascript">
$(document).ready(function() {
var options = {
target:'#output1',
beforeSubmit: onBeforeSubmit,
success: onSuccess,
error: onError
};
$('#CommentEditForm').ajaxForm(options);
});
</script>
In my controller function when I receive form data which is not validated by model I change layout for ajax layout and return view without default layout's html stuff around and append it into div#output1 in my view.
It seems to be OK but now I have in view except form but div#output1 and javascript code. I know where is my problem - I need solution how to return only form data and not javascript code and div#output1 stuff. This logic will be used in all my application so I would like to avoid requirement to hard code {if...else} conditions in all my views.
Upvotes: 1
Views: 1815
Reputation: 15424
thaJezath answer is good but there are few more things:
It's easier and more DRY to use CakePHP Js helper for all ajax stuff:
<div id="output">
<?php
echo $this->Form->create();
echo $this->Form->input('input1');
echo $this->Form->input('input2');
echo $this->Js->submit('submit',array('update' => '#output');
?>
</div>
This will automaticly add buffered script which will handle ajax submit for you. But you will need echo $this->Js->writeBuffer();
line in your layout just before </body>
tag.
But this still returns <div id="output">...
- if you will change to 'update' => '#content'
, it will reload whole content div.
In your view file:
<div id="output">
<?php $this->start('ajax-content'); // this line starts new block ?>
<?php
echo $this->Form->create();
echo $this->Form->input('input1');
echo $this->Form->input('input2');
echo $this->Js->submit('submit',array('update' => '#output');
?>
<?php
$this->end(); // this line ends block
echo $this->fetch('ajax-content'); // this line print contents of block
?>
</div>
And in your /View/Layouts/ajax.ctp:
<?php
// next 2 lines only ensure that ajax-content block exists
// if not it will be just empty string
$this->startIfEmpty('ajax-content');
$this->end();
echo $this->fetch('ajax-content'); // this line outputs ajax-content block (the form)
?>
So to sum up this method encloses content you want to return in ajax content inside a view block. Then ajax layout instead printing whole view ($this->fetch('content');
) it prints just contents of ajax-content block ($this->fetch('ajax-content');
). This way you can mark in every view all content you want to return during ajax request.
The lines:
$this->end(); // this line ends block
echo $this->fetch('ajax-content'); // this line print contents of block
may not be handy - it would be good idea to put all block-recording code in your own helper to use it simply:
<div id=...
$this->AjaxContent->start();
your form here
$this->AjaxContent->stop();
</div>
As thaJezath wrote in comments JsHelper will be deprecated in future releases so it will be safer to use view blocks as he said. HtmlHelper has convinient way of doing this:
<?php $this->Html->scriptStart(array('inline' => false)); ?>
$(document).ready(function(){
// your code here
});
<?php $this->Html->scriptStart(array('inline' => false)); ?>
And this will add your script to the viewBlock "script"
which is printed in default layout by $this->fetch('script');
Upvotes: 4
Reputation: 28987
You should use the JavaScript buffer or a 'view block' to output your JavaScript, this way you can output the javascript inside your Layout, not in your view. As you're already switching to a different layout (or no layout) for your AJAX requests, the script will not be included when retrieving via AJAX.
Change your view to this:
Modify the content of your view to this:
<div id="output1">...here goes my CakePHP PHP form code...</div>
<?php
/**
* I'm using 'heredoc' notation so that you don't have to escape quotes and '$'
* @link http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc
*/
$script = <<< JS
$('#CommentEditForm').ajaxForm({
target:'#output1',
beforeSubmit: onBeforeSubmit,
success: onSuccess,
error: onError
});
JS;
/**
* Append the JavaScript to the JavaScript-buffer
* using the JS helper
*
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html
*/
$this->Js->buffer($script);
Output the JavaScript in your layout (e.g. Layouts/default.ctp)
<!-- rest of your layout here -->
<?php
// Output the JavaScript and wrap it in a 'onDomready()' wrapper
echo $this->Js->writeBuffer();
?>
</body>
</html>
NOTE: You DONT have to add the 'onDomready()' to your scripts when using the JS-buffer, CakePHP will add them automatically when outputing the buffer with $this->Js->writeBuffer()
NOTE2: Using the output-buffer allows you to add JavaScript to the buffer multiple times. For example, if you're using 'elements', you are able to add javascript to the buffer as well. This allows you to add script 'as-you-go' and output them all at once at the end of your body
Upvotes: 3