I create a function in CakePHP controller class to process AJAX request. But I found different result when using CakePHP function and simple (Non-MVC) PHP code. My problem is when it goes to submit() process. When using CakePHP function it returns blank page.
Here is the AJAX request code that I use:
var userdata = {username : $("#UserUsername").val()};
$.ajax({
type:'POST',
url: 'http://localhost/mycakephp/users/login',
data: userdata,
success: function(data){
if(data==0){
alert("empty");
} else {
$("#UserLoginForm").submit();
}
}
});
But when I pointed the url to external site like this:
url: 'http://localhost/test/test.php'
Which test.php is a simple PHP code to handle request, submit process works fine.
Sorry, but your code looks bizarre to me: There you have a login form, you send using ajax your username calling the Controller "UsersController" / function "login", and when you have an answer from this function, then you submit again another form ("#UserLoginForm") and send it again to the controller? You are sending two forms! Most probably this is not what you want. Correct me if I am wrong.
I guess what you want is just submit the UserLoginForm and wait for an answer, whatever it is OK or NotOK, and finally show this result.
You have two options to do this: either CakePHP way or your own ajax code using JQuery. I like to use both, depending on the user experience I want to get.
1. CakePHP way
Include JS Helper in the controler using the public $helpers = array('Js'); and then create a Form in the view, using the submit from the JsHelper.
View
<?php
echo $this->Form->create();
echo $this->Form->input('username');
echo $this->Form->input('whatever');
// use the Js submit from JsHelper
echo $this->Js->submit('Send', array(
'url'=> array('controller' => 'users', 'action' => 'login'),
'update' => '#update_ajax_div',
));
echo $this->Form->end();
// Next line is actually very important in order
// to print the automatically created ajax code from JsHelper.
echo $this->Js->writeBuffer();
?>
<div id="update_ajax_div">
this will be overwritten after submit.
</div>
Controller
In the controller all the data in the form will be sent in the $this->data[] array. For example $this->data['Users'] if this is the Model being used in the Form->create().
The code is pretty standard, except the layout, which must be set to ajax.
public function login(){
// print the data being sent
$dataFromAjaxLink = $this->data[];
$v = var_export($dataFromAjaxLink, true);
$this->log("Ajax log: ".$v, 'debug');
if(isset($this->data['User'])){
$user_name = $this->data['User']['username'];
...
// do your stuff
}
// the answer must be ajax layout
$this->layout = "ajax";
// I like to use elements when using ajax, it keeps the folders clean
// in this example /app/View/Elements/display_ajax_result.ctp
$this->render('/elements/display_ajax_result');
}
The content of this element will be printed in the div "update_ajax_div"
2. Pure Ajax way
The second version is done by manually typing ajax code in <script> tags. This solution gives you more freedom, allowing you to do more complex stuff, but the code is not so clean!
The following JQuery code must be inside some button/div/whatever event...
$(document).ready(function(){
$(".someButton").click(function() {
// create the json data to be sent
var username = $(....).val();
var dataString = ...
// call ajax
$.ajax({
type: "POST",
// never type full paths as in your example. They are sources of errors!
url: "<?php echo $this->Html->url(array(
"controller" => "users",
"action" => "login")); ?>,
data: dataString,
cache: false,
success: function(html){
$("#update_ajax_div").html(html);
}
});
...
The controller is the same as the CakePHP way. Remember to add ajax layout.
I hope it helps you.
According to your comment, if you use the SecurityComponent, you could disable POST validation on the login action. In your UsersController, add this:
function beforeFilter()
{
parent :: beforeFilter();
switch($this->request->params['action'])
{
case 'login':
$this->Security->validatePost = false;
$this->Security->csrfCheck = false;
break;
}
}
But off course you loose the value added by the SecurityComponent on the login action.
Related
I am beginner to CakePHP and trying the send the textbox value during change function to my controller action using ajax.
Can someone help to how to pass the value form jquery to cakephp controller. If there is example code could great.
Let's say you want to send your data to a method called 'ajax_process' in the users controller. Here's how I do it:
in your view .ctp (anywhere)
<?php
echo $this->Form->textarea('text_box',array(
'id' => 'my_text',
));
?>
<div id="ajax_output"></div>
In the same view file - the jquery function to call on an event trigger:
function process_ajax(){
var post_url = '<?php echo $this->Html->url(array('controller' => 'users', 'action' => 'ajax_process')); ?>';
var text_box_value = $('#my_text').val();
$.ajax({
type : 'POST',
url : post_url,
data: {
text : text_box_value
},
dataType : 'html',
async: true,
beforeSend:function(){
$('#ajax_output').html('sending');
},
success : function(data){
$('#ajax_output').html(data);
},
error : function() {
$('#ajax_output').html('<p class="error">Ajax error</p>');
}
});
}
In the UsersController.php
public function ajax_process(){
$this->autoRender = false; //as not to render the layout and view - you dont have to do this
$data = $this->request->data; //the posted data will come as $data['text']
pr($data); //Debugging - print to see the data - this value will be sent back as html to <div id="ajax_output"></div>
}
Disable cake's security for the ajax_process method, in AppController.php:
public function beforeFilter() {
$this->Security->unlockedActions = array('ajax_process');
}
I haven't tested any of this code but it should give you what you need
I am creating controller in Code Igniter and make form in ExtJs 4.2.1 now from where i call control and how?
i used url property of form and put controller name there but nothing happen
Update
I think i am not clearing my question actually i want to post data through submit function in which i pass data to php file in my server side i use Code Igniter Rest Api so here i want pass data to specific controller
ExtJs is a javascript framework and is executed on the client side. It has its own MCV system.
It makes no sense to mix up a php controller with a javascript view.
Be sure to read the introduction to MVC in ExtJS.
Also in ExtJS you don't call the controller. On initialisation of the app, all controllers get lloaded. In the controller you define what it has to control, and from then on the magic hhappens: The events defined in the controller are fired whenever needed.
In ExtJS 3.3.1
In login form put the buttons and call function submit_login();
buttons: [{
text: 'Login',
handler: function() {
submit_login();
}
}]
Submit_login() code is, I used Ext.Ajax.request to submit login parameters
You can debug the message with alert(response.responseText):
function submit_login() {var useridx = Ext.getCmp('useridx').getValue();var userpasswordx = Ext.getCmp('userpasswordx').getValue();Ext.Ajax.request({url:'".$url."', method:'POST',
params :{useridx:useridx,userpasswordx:userpasswordx},
success:function(response){
//alert(response.responseText);
//return;
var jsonData = Ext.util.JSON.decode(response.responseText);
var resultMessage = jsonData.Message;
var isLogin = jsonData.isLogin;
if (isLogin)
{
window.location = '';
}
else
{
Ext.Msg.alert('Info',resultMessage);
}
},
failure: function(){
Ext.Msg.alert('Not OK');
}
});
}
variable $url is:
$url = "index.php/apps/login";
You can create Apps controller
and create function login
public function login()
{
$this->load->view('login');
}
Create login.php in view
if ($i==1) {
//session_start();
$this->session->set_userdata('userid',$useridx); echo '{"success" : true, "isLogin": true,"Message" : "User Successfully Login"}';
} else {
echo '{"success" : true, "isLogin": false, "Message" : "Salah User: '.$useridx.' dan Password "}';
}
You also do this in Ext JS 4.2.1 with same code.
This is works for me
Andrex Maulana
How do i set up ajax in cakephp without using the default ajax helper? The default ajax helper puts the js code on the page itself, I don't want that. I want it to be set in a seperate js file (ie general.js) instead. How do i do that? I have pagination already set up.
First make sure you have jquery set up. In your default.ctp (View/Layouts/default.ctp) add the following line within the <head> section:
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
In your AppController.php file (Controller/AppController.php) add the following lines
function beforeRender() {
if ($this->request->is('ajax')) {
$this->layout = false;
}
}
This causes the behaviour that when an ajax call is made to an controller action only the view itself is loaded rather than the whole layout.
In your general.js file (webroot/js/general.js) add the following code:
$(document).ready(function(){
ajaxPagingNavigation();
});
function ajaxPagingNavigation() {
$(".paging a").click(function(e) {
$.ajax({
url: $(this).attr('href'),
cache: false
}).done(function( html ) {
$("#content").html(html);
ajaxPagingNavigation();
});
e.preventDefault();
});
}
Has anyone found a way to intercept the default Form::postLink() forms with Jquery?
I would like the form to work without JS (therefore the postLink).
But with JS enabled I want to intercept the post and call it via AJAX.
<?php echo $this->Form->postLink('Delete', array('action'=>'delete', $prospect['Prospect']['id']), array('class'=>'postLink', 'escape'=>false), __('Sure you want to delete # %s?', $prospect['Prospect']['id'])); ?>
generates:
<form action="/admin/prospects/delete/4f61ce95-2b6c-4009-9b89-07e852b0caef" name="post_4f648f773923b" id="post_4f648f773923b" style="display:none;" method="post">
<input type="hidden" name="_method" value="POST"/>
</form>
<a href="#" class="postLink" onclick="if (confirm('Sure you want to delete # 4f61ce95-2b6c-4009-9b89-07e852b0caef?')) { document.post_4f648f773923b.submit(); } event.returnValue = false; return false;">
Delete
</a>
The main problem is that the js is placed inline here. Therefore always triggers even if I try to intercept the click event (or the post event - tried that too):
<script>
$(document).ready(function() {
$('table.list a.postLink').click(function(e) {
e.preventDefault();
alert('Handler for .submit() called.');
// TODO: do ajax request here and return false
return false;
});
});
</script>
So in the end the form always submits normally and redirects - either ignoring any ajax call (catching the form submit) or posting/redirecting regardless of an ajax call just made (catching the click event).
I would like to delete this record via AJAX and - if successful - just remove that table row from DOM. It would be great if one doesn't have to modify all 300+ "delete buttons" in the application for it, though.
If everything fails I could probably still override the FormHelper (extend it and alias it). But I was hoping on a less invasive solution here.
I know this is old, but for any of those searching:
You need to first remove the 'onclick' attribute added to the delete
link.
Then, you add a .click function to the delete link
You need the url (which can be hardcoded or retrieved from the form, which is always the prev element in cakephp Form->postLink
Here is the code:
$(function(){
$('a:contains("Delete")').removeAttr('onclick');
$('a:contains("Delete")').click(function(e){
e.preventDefault();
var form = $(this).prev();
url = $(form).attr("action");
$.post(url);
return false;
});
});
jymboche - what a genius
why didnt i think of it myself?
Well, here is the modified answer of yours:
$(document).ready(function() {
$('table.list a.postLink').removeAttr('onclick');
$('table.list a.postLink').click(function(e) {
e.preventDefault();
if (!confirm('<?php echo __('Sure?')?>')) {
return false;
}
var form = $(this).prev();
var url = $(form).attr("action");
var tr = $(this).closest('tr');
url = url + '.json';
$.post(url).success(function(res) {
if (res.error) {
alert(res.error);
return false;
}
tr.fadeOut(200);
}).error(function() {
alert("Error");
})
return false;
});
});
This is for future reference only.
I will still accept your answer as you gave me the right idea.
jymboche's solution helped me to get to a working answer, but it didn't work fully for me, due to some security cake plugins that I have installed.
Here's what worked for me:
$(function(){
$('a:contains("Delete")').removeAttr('onclick');
$('a:contains("Delete")').click(function(e){
e.preventDefault();
var form = $(this).prev();
var url = $(form).attr("action");
$.ajax({
type: 'POST',
cache: false,
url: url,
data: $(form).serialize(),
success: function(msg) {
// do any extra calls you need to refresh the page
}
});
return false;
});
});
Just an idea, haven't tested it:
<?php echo $this->Form->postLink('Delete', array('action'=>'delete', $prospect['Prospect']['id']), array('class'=>'postLink', 'onclick' => false, 'escape'=>false), __('Sure you want to delete # %s?', $prospect['Prospect']['id'])); ?>
Couple of issues with the current solutions...
First and foremost, the postLink method requires Javascript to be enabled. From Cake's doco:
"Creates an HTML link, but access the url using method POST. Requires javascript to be enabled in browser."
If javascript is disabled, you just get the exact same output - a hidden form, and a link that tries to submit that form with Javascript (but fails, since JS is turned off).
Second, although it will work, it seems weird to use the postLink method, and then use Javacript to undo precisely all the magic that the postLink method creates.
If you want a non-javascript friendly solution, all you have to do is create a regular form that points to the delete method, and put a link below it like this:
<?php echo $this->Form->create('DefaultAvailability', array('url' array('action' => 'delete', $myRecord['ModelName']['id'])));?>
<?php echo $this->Form->end('Delete (no JS)');?>
<a href='#'>Delete (With JS, use AJAX)</a>
Then, for cases when there's no javascript, hide the link below, and the form will work as normal.
For cases when there is javascript, hide the form, and use javascript to make your delete link trigger a submit on your delete form, and handle that submit with ajax.
I've translated the previous jQuery version to Mootools
//We start with foreach, to select all ajax buttons on the page
$$('.ajaxbutton').each(function(item,index){
//remove onClick
item.removeProperty('onclick');
//attach click event
item.addEvent('click', function(e){
//stop click (in my case the form is inside another link)
e.stop();
var form = item.getPrevious();
url = form.get('action');
new Request({
url: url,//url
method: 'post',//method
onSuccess: function(responseText){
//This is not required, we are dimming the button on success
item.getParents()[0].tween('opacity',0.5)
}
}).send();
return false;
});
})
I'm working with CakePHP 1.3.7 and I'm trying to do the following:
On a given page, the user can click a link (or image, or button, doesn't matter) that passes a parameter which is saved into a database. BUT, all this, without refreshing the page.
I've been doing some research and I believe I need to use AJAX as well to acomplish this. However, I can't find the a good example/explanation on how to do it.
I think that the idea is to create the link using AJAX, which calls the controller/action that would receive the variable as a parameter and performs the operation to save it in its corresponding field/table of the DB.
Does anyone have a small example of what I want to do? Or maybe point me to some tutorial that explains it... Thanks so much in advance!
EDIT
Well, thank you guys for your replies. THey're not working directly, but I think I'm getting closer to what I want. Here's what i'm doing now:
I have this code in my view:
<div id="prev"><a>click me</a></div>
<div id="message_board"> </div>
I call this JS file:
$(document).ready(function () {
$("#prev").click(function(event) {
$.ajax({data:{name:"John",id:"100"}, dataType:"html", success:function (data, textStatus) {$("#message_board").html(data);}, type:"post", url:"\/galleries\/add"});
return false;
});
});
And my add action in my galleries controller looks like:
function add() {
$this->autoRender = false;
if($this->RequestHandler->isAjax()) {
echo "<h2>Hello</h2>";
print_r($this->data);
$this->layout = 'ajax';
if(!empty($this->data)) {
$fields = array('phone' => 8, 'modified' => false);
$this->User->id = 6;
$this->User->save($fields, false, array('phone'));
}
}
}
When clicking on the '#prev' element, I get a response from the add action, I know because the text 'Hello' is printed inside #message_board. And it does this without refreshing the page, which is why I need. My problem is that I can't make the $.ajax() function to send any data, when it gets to the controller the $this->data is empty, so it never goes inside the if that saves the info to the database (right now it's saving just an easy thing, but I will want it to save the data that comes from the view).
Can anyone see what am I doing wrong? How can I send the data to the controller?
CakePHP does not matter, most of the code you would need for this would be at clientside. Implementing AJAX by yourself is a pain in the $, so you really want to use a library; currently the most popular is probably jQuery. There's a bunch of examples on their AJAX page: http://api.jquery.com/jQuery.ajax/
So, assuming you have something like this in the document:
<form id="s">
<input id="q"/>
<input type="submit" href="Search!"/>
</form>
<div id="r"/>
you can put this in the JavaScript:
$('#s').submit(function(evt) {
evt.preventDefault();
$.ajax({
url: 'foo.php',
data: {
query: $('#q').val()
},
success: function(data) {
$('#r').html(data);
}
});
return false;
});
Then your foo.php only needs to return the fragment HTML that would go into the div#r.
EDIT: I forgot to stop the submit :( Thanks to #Leo for the correction.
EDIT: I can see what your confusion is about. You will not get a data. I haven't worked with CakePHP, but I assume $this->data is what you'd get from $_REQUEST['data']? You don't get that on the server. data is a hash of what is getting submitted; you will directly get the $_REQUEST['name'] and $_REQUEST['id'] (which, I assume, translate into CakePHP as $this->name and $this->id).
You need to add
$('#s').submit(function(evt) {
evt.preventDefault();
To prevent a page refresh, as in Amadans answer just refer to your controller/ action in the url variable
$('#s').submit(function(evt) {
$.ajax({
url: '/patients/search/',
data: {
query: $('#q').val()
},
success: function(data) {
$('#r').html(data);
}
In the patients/add controller action make sure you return a valid result ( in json is good )