Populating my jquery autocomplete with contents of an ajax call to cakephp - ajax

I have an input field that I'm turning into a jqueryUI autocomplete:
$( "#autocomplete" ).autocomplete({
autoFocus: true,
source: mylist
});
The mylist variable is just a string in the array format ['Value1','Value2,'Blah'] which i originally just hardcoded into the script.
Now I want the mylist variable to be the result of an ajax call to a function in my cakephp app. The function is basically as follows, it just grabs all the data as a list, and json encodes it.
public function source() {
$this->layout = 'ajax';
$countries=$this->Country->find('list',array('fields'=>'Country.country'));
ChromePhp::log($countries);
echo json_encode($countries);
}
This outputs:
{"1":"Afghanistan","2":"Albania ","3":"Algeria ","5..
My issue is getting the output of this function, (which ends up in the ajax success callback as 'data') into the correct format to place into the options array of the autocomplete.
I can get as far as console logging each value, but I'm stumped. Basically clutching at straws at the correct syntax.
$.ajax({
type: "GET",
dataType: "json",
url: "/source/",
success: function(data){
/*
magic array string creation code would go here instead of my code below...
*/
$.each(data, function(i, item) {
console.log(item);
});
console.log('data',data);
}
})

The autocomplete plugin can do a lot of the work for you if you give it things in the right format.
I would start by re-indexing the $countries variable to start from 0. You can use the array_values() function for that:
echo json_encode(array_values($countries));
This should give you the JSON in the format of:
['Afghanistan','Albania','Algeria',...]
Then you can change the source property in the autocomplete code to be a url for your source action.
$( "#autocomplete" ).autocomplete({
autoFocus: true,
source: "/your_controller/source"
});
The autocomplete plugin won't filter the results for you, instead a query string is added to the url with a term field (e.g. /your_controller/source?term=foo) so you need to modify your find() method to use this.
$countries = $this->Country->find('list', array(
'fields' => 'Country.country',
'conditions' => array(
'Country.country LIKE' => $this->request->query['term'] . '%'
)
));
You can read more about the different types the source option can accept in the autocomplete on the API Documentation.

Related

How to fetch ajax request data in cakephp 2 controller?

I'm trying to send some data from my view to my controller via ajax. How do I retrieve this data in my action?
I've tried jQuery's $.ajax and $.post methods, providing the url and data, but using $this->data, $this->request->data, $_POST, $_GET or $_REQUEST doesn't work (all return as empty arrays).
$.ajax({
url: "<?php echo Router::url( array("controller" => "Progression", "action" => "submit", $user['User']['id']) ); ?>",
type: 'post',
data: { name: "John" }
}).done( function(data) {
console.log(data);
});
function submit() {
$this->request->allowMethod('ajax');
$this->autoRender = false;
$data = array();
$data['answer'] = $this->request->data; // or any of $_POST, $_GET, etc.
return json_encode($data);
}
My console always keeps printing {"answer":[]}. I checked the network tab of my devtools and the data is successfully listed under Form data, yet I can't seem to get hold of the data in the action.
EDIT:
Thanks to Greg Schmidt I found out that my request indeed got redirected: first it gives me a 302, then it makes a new request without the post data and returns a 200. I just can't find what the critical difference is between the two requests (URLs look the same, no case difference or anything). Can anybody help me with that?
First request:
Second request:

Using Ajax return data in the on success parameter

I am trying to use the a parameter from data returned from an ajax call in the success return function of that ajax call.
As per code below, I submit of my modal an ajax call is sent to add_events.php with a $_POST['title'] paramater. I want the resultant 'title' string to be used in the on success function (msg) as 'var title' so it can then be used in the renderEvent that follows.
It seems possible, but I can't find the correct syntax to do this :( Any assistance would be appreciated.
Thank you,
Nigel
$(function() {
//twitter bootstrap script
$("button#submit").click(function(){
$.ajax({
type: "POST",
url: "add_events.php",
data: $('form#add-event-form').serialize(),
success: function(msg){
$("#thanks").html(msg)
$("#modal-new-event").modal('hide');
var title = 'This is not the correct title'; //WANT THIS TO BE THE RETURN VALUE FOR title THAT WAS POSTED TO PHP FILE
var eventData = { title: title };
$('#calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
},
error: function(){
alert("failure");
}
});
$('#calendar').fullCalendar('unselect');
});
});
You could just grab the title from where you posted it, provided it has an id, say, if it was a text input like:
<input id="title">AWESOME TITLE</input>
You can grab it from anywhere with
$('#title').val(); // "AWESOME TITLE"
Another option would be to return the title posted in a json and use it in your success callback like
{"msg":"your message", "title":"your title"}
I don't know if I'm getting well what you want but I'm gonna take the risk. If what you want is to grab the value that you sent to your php page on the server, then you do this:
var title = $('#title').val()
That is assuming that the text field has title as id. If you have name="title" instead of id="title", then:
va title = $('input[name="title"]').val();

.done attachment not working with ajax update to file, works with read from file

Attaching .done .fail and .always to ajax calls is now doable for me - it is "easy" when the script is at the bottom of the html page.
Now I want to create generalized ajax functions that I can use just by including a js file in the header. I've been successful with ajax functions that read data from server (.done always works). I'm having problems when I just write or update data to the server (no return of data). Here are the specifics-
Standard ajax add/update call that always works - in script tags at bottom of page.
$.ajax({
type: 'POST',
url: 'supdateajaxfunctiontestbackend.php',
data: {localid: localid,
firstname: firstname,
lastname: lastname}
}).done(function(){ alert('Done with Add/Update!'); });
If I create a function at the bottom of the page, or add the function to a js file, this add/update always works.
function generalWriteAjax(filetocall, datatosend) {
$.ajax({
type: 'POST',
url: filetocall,
data: datatosend
}).done(function(){ alert('Done with Add/Update!'); });
}
I would like to detach the .done from the function, and call the .done when attached to a separate function/object. The following code works fine WHEN THERE IS DATA RETURNED FROM THE SERVER. (a separate generalReadAjax function that asks for server data). The done is attached to an object that is returned from the server (This concept I found here on Stackoverflow).
backenddata = generalReadAjax('readtesttablebackend.php');
displayData(backenddata);
backenddata.done(function(){ alert("Done with read!"); });
});
I have tried all of the following with the WRITE/UPDATE only function, and none of them work.
generalWriteAjax(filetocall4update, datatosend4update).done(function(){ alert('Done function'); });
generalWriteAjax(filetocall4update, datatosend4update).when(function(){ alert('Done function'); });
generalWriteAjax(filetocall4update, datatosend4update).then(function(){ alert('Done function'); });
generalWriteAjax(filetocall4update, datatosend4update);
createdonealert = generalWriteAjax(filetocall4update, datatosend4update);
createdonealert.done(function(){ alert('Done function'); });
createdonealert.when(function(){ alert('Done function'); });
createdonealert.then(function(){ alert('Done function'); });
So obviously, there is a difference in the way the promise is handled between a "go get me data" and "here is data, please store it".
I even put an echo "Done"; at the bottom of the update php file just to return something, and still no luck.
I've searched this site and google with combinations of:
ajax .done attach add update not working promise
and have found nothing that deals with my specific example.
Can someone give me some guidance?
I thank you in advance.
Well, no one has responded, and I've learned a bit by hacking on this for the last day. Here are some things I THINK I've learned:
If you create a general callable function using ajax, it does not act the same as an "inline" ajax - you do not get the same callback actions as you do when the ajax code is at the bottom of an HTML page between script tags.
If you return something from the server, the ajax function acts similarly to when it is between script tags.
If you DO NOT return data from the server, the ajax function does NOT act the same as when it is inline.
So what I've done is on all php files that are "write/update" only (no data returned), I add a little code to the bottom of each php file that returns a small amount of json "junk". With this "junk" the ajax function acts like a regular ajax call between script tags at the bottom of the page.
It's a kludge, but it works. Here is the code at the bottom of a read/update php file that normally would NOT return anything. It now returns a json array regarding "John":
$json = array('firstname' => 'John');
echo json_encode($json);
Here is the function in the attached js file:
function generalWriteAjax( filetocall, datatosend ) {
return $.ajax({
type: 'POST',
url: filetocall,
data: datatosend,
dataType: 'json'
});
}
Here is the code on the page that calls the .js function:
$("#clicktoupdate").click(function(e) {
var localid = $('#idnumber').val();
var firstname = $('#updatefirstname').val();
var lastname = $('#updatelastname').val();
var filetocall4update = 'supdateajaxfunctiontestbackend.php';
var datatosend4update = {localid: localid, firstname: firstname, lastname: lastname};
generalWriteAjax(filetocall4update, datatosend4update).done(function(){ alert('Done inline'); });
});//end of update click
I wish I understood the details, but this is an empiric solution that works.
Comments from the experts would be nice.
Thanks for looking!

Phpfox implement autocomplete with ajax

I have this in my javascript file
$("#searchPlaces" ).autocomplete({
source:function( request, response ) {
$.ajaxCall('mymodule.getcities', 'startsWith='+request.term);
},
autoFocus: true
});
And this is in my ajax php file.
public function getcities(){
$cities = array("1" ,"2", "3", "4");
$this->call(json_encode($cities));
}
It returns the array as json just fine, but nothing shows up in the autocomplete field.
Would anyone know how to accomplish this task in phpfox using the ajaxCall function?
Thanks.
So I was able to get around the issue. The issue is autocomplete needing the response specified. ajaxCall doesn't have a real callback on success, so there is no way to set the response with the data that gets returned. I decided to go a round about way and set everything manually. This is what I came up with.
include\component\controller\mycontroller.class.php
$this->template()->assign(array('token' => Phpfox::getService('log.session')->getToken());
template\default\somehtml.html.php
<input id="security_token" type="hidden" name="phpfox[security_token]" value="{$token}" />
static\jscript\myjavascript.js
$("#searchPlaces" ).autocomplete({
source:function( request, response ) {
$.ajax({
url: "/static/ajax.php",
minLength: 1,
dataType: "json",
data: {
startsWith: request.term,
'core[security_token]': $("#security_token").val(),
'core[ajax]': true,
'core[call]': 'mymodule.myfunction'
},
success: function( data ) {
response( data );
}
});
},
autoFocus: true
});
include\component\ajax\ajax.class.php
public function myfunction(){
$yourdata = array("1" ,"2", "3", "4");
$this->call(json_encode($yourdata ));
}
Basically the security token is set via a hidden element. The url will always be url: "/static/ajax.php", as this will take care of calling the ajax file for you. 'core[call]': 'mymodule.myfunction' this is set to how you would use $.ajaxCall('mymodule.myfunction'). All you need to do is find the autocomplete items you want to return as normal now.
Hopefully this helps in case someone else gets in the same situation.
The default phpfox $.ajaxCall actually returns a jQuery jqXHR object.
So, instead of rebuilding the entire ajax call manually, one could still use phpfox's $.ajaxCall and set the autocomplete response inside the .done() promise callback:
$("#searchPlaces" ).autocomplete({
source:function( request, response ) {
$.ajaxCall('mymodule.getcities', 'startsWith='+request.term)
.done(function( data ) {
response( $.parseJSON(data) );
});
},
autoFocus: true
});
Note that the $.ajaxCall ajax request uses 'script' as dataType, so you need to do your own parsing of the returned string, in this case it's a json string and $.parseJSON() will do the trick.

How do I perform a jQuery ajax request in CakePHP?

I'm trying to use Ajax in CakePHP, and not really getting anywhere!
I have a page with a series of buttons - clicking one of these should show specific content on the current page. It's important that the page doesn't reload, because it'll be displaying a movie, and I don't want the movie to reset.
There are a few different buttons with different content for each; this content is potentially quite large, so I don't want to have to load it in until it's needed.
Normally I would do this via jQuery, but I can't get it to work in CakePHP.
So far I have:
In the view, the button control is like this:
$this->Html->link($this->Html->image('FilmViewer/notes_link.png', array('alt' => __('LinkNotes', true), 'onclick' => 'showNotebook("filmNotebook");')), array(), array('escape' => false));
Below this there is a div called "filmNotebook" which is where I'd like the new content to show.
In my functions.js file (in webroot/scripts) I have this function:
function showNotebook(divId) {
// Find div to load content to
var bookDiv = document.getElementById(divId);
if(!bookDiv) return false;
$.ajax({
url: "ajax/getgrammar",
type: "POST",
success: function(data) {
bookDiv.innerHTML = data;
}
});
return true;
}
In order to generate plain content which would get shown in the div, I set the following in routes.php:
Router::connect('/ajax/getgrammar', array('controller' => 'films', 'action' => 'getgrammar'));
In films_controller.php, the function getgrammar is:
function getgrammar() {
$this->layout = 'ajax';
$this->render('ajax');
}
The layout file just has:
and currently the view ajax.ctp is just:
<div id="grammarBook">
Here's the result
</div>
The problem is that when I click the button, I get the default layout (so it's like a page appears within my page), with the films index page in it. It's as if it's not finding the correct action in films_controller.php
I've done everything suggested in the CakePHP manual (http://book.cakephp.org/view/1594/Using-a-specific-Javascript-engine).
What am I doing wrong? I'm open to suggestions of better ways to do this, but I'd also like to know how the Ajax should work, for future reference.
everything you show seems fine. Double check that the ajax layout is there, because if it's not there, the default layout will be used. Use firebug and log function in cake to check if things go as you plan.
A few more suggestions: why do you need to POST to 'ajax/getgrammar' then redirect it to 'films/getgrammar'? And then render ajax.ctp view? It seems redundant to me. You can make the ajax call to 'films/getgrammar', and you don't need the Router rule. You can change ajax.ctp to getgrammar.ctp, and you won't need $this->render('ajax');
this is ajax call
$(function() {
$( "#element", this ).keyup(function( event ) {
if( $(this).val().length >= 4 ) {
$.ajax({
url: '/clients/index/' + escape( $(this).val() ),
cache: false,
type: 'GET',
dataType: 'HTML',
success: function (clients) {
$('#clients').html(clients);
}
});
}
});
});
This the action called by ajax
public function index($searchterm=NULL) {
if ( $this->RequestHandler->isAjax() ) {
$clients=$this->Client->find('list', array(
'conditions'=>array('LOWER(Client.lname) LIKE \''.$searchterm.'%\''),
'limit'=>500
));
$this->set('clients', $clients);
}
}
This is a function I use to submit forms in cakephp 3.x it uses sweet alerts but that can be changed to a normal alert. It's very variable simply put an action in your controller to catch the form submission. Also the location reload will reload the data to give the user immediate feedback. That can be taken out.
$('#myForm').submit(function(e) {
// Catch form submit
e.preventDefault();
$form = $(this);
// console.log($form);
// Get form data
$form_data = $form.serialize();
$form_action = $form.attr('action') + '.json';
// Do ajax post to cake add function instead
$.ajax({
type : "PUT",
url : $form_action,
data : $form_data,
success: function(data) {
swal({
title: "Updated!",
text: "Your entity was updated successfully",
type: "success"
},
function(){
location.reload(true);
});
}
});
});

Resources