I don't want to refresh a page when I am searching through a database eg. on post, so I had help in using a $.post call which works for sending information. There is a .done(function( data ){ line which I haven't used yet.
I also came across this question which I'm not sure if this ties to my question.
Return $.get data in a function using jQuery
I'm trying to search through a database, string match, and return the rows with matching strings. But I want to do this without refreshing the page so I would think that I am using the $.post call and using the .done(function( data ){ which is triggered by javascript (a button).
So I have two parts, the page I'm on and a separate PHP page that processes the call when made.
How do I make the bridge where I can return the data back? Or is there an easier way to do this?
The method .done(function(){}) is exactly what You would like to use, but You can also take a look at third argument (callback) of $.post function.
On server side, do all the queries and prepare the stuff in jsoned array like:
// set up data to send
$contentArray = [
'content' => 'Some content',
'foo' => 'bar',
];
$jsonResults = json_encode($contentArray);
// you can always send header('Content-Type: application/json'); instead of using simple die function.
die($jsonResults);
Then on client side:
<div class="content-container"></div>
<script type="text/javascript">
function someFunc() {
(...)
$.post(addr, values, function(res) {
var response = $.parseJSON(res);
$('.content-container').html(response.content);
});
}
</script>
This should update the content of the .content-container class only. You can send as much as you want, even prepared view to be displayed in the container. This is up to You.
EDIT:
Just to be sure, you're calling someFunc() on some button click event, right? If not, do it as follows:
<div class="content-container"></div>
Click here
<script type="text/javascript">
function changePageContent(addr, contentId) {
$.post(addr, {contentId:contentId}, function(res) {
var response = $.parseJSON(res);
$('.content-container').html(response.content);
});
}
$('.callMe').on('click', function() {
changePageContent($(this).attr('href'), $(this).attr('data-content-id'));
return false;
});
</script>
someScript.php:
<?php
// you should force your script to allow only XML HTTP request here
if(empty($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
die('AJAX requests only..');
}
// always remember to escape somehow your post values before you use them
$contentId = is_numeric($_POST['contentId']) ? intval($_POST['contentId']) : null;
if (null == $contentId) (...) // throw exception or return status=false
// do your mysql query like: "SELECT * FROM content WHERE id=".$contentId;
// well, it would be better to send headers instead of that
die(json_encode([
'status' => true, // this is a good practice to send some info, if everything is fine, if mysql row has been found etc..
'result' => $result, // mysql row, this is just in case you need other values to display
'content' => $result['content'], // I assume you have 'content' column in your mysql
]));
?>
Take a look at the docs for Ajax, there really is a lot of info there which will help.
In short, you could do something like this:
function myPost() {
// Set the data
var data = {
'key' : 'value',
'key_2' : 'value_2'
};
// Do the post
$.post( '/your-url/', data, callBack );
}
function callBack( data ) {
// If the $.post was successful
success: function( data ) {
// do stuff
console.log( data ); // returned from your endpoint
},
// If there was an error
error: function( jqXHR, textStatus ) {
// do stuff
console.log( "Request failed: " + textStatus );
}
}
// On click of your element, fire the post request
$('#element').on('click', function() {
myPost();
});
Related
I can send the data to admin-ajax.php and see that the data exists via my dev tools, however, I cannot seem to be able to take that data and update an ACF field, or perhaps my function to do that is not running.
Here is my PHP:
// define the actions for the two hooks created, first for logged in users and the next for logged out users
add_action( 'wp_ajax_add_dog_to_favorites', 'add_dog_to_favorites' );
add_action( 'wp_ajax_nopriv_add_dog_to_favorites', 'login_to_add_to_favorites' );
// define the function to be fired for logged in users
function add_dog_to_favorites() {
// nonce check for an extra layer of security, the function will exit if it fails
if (!wp_verify_nonce( $_REQUEST['nonce'], 'add_dog_to_favorites_nonce' )) {
exit('Woof Woof Woof');
}
// Get the post_id and user_id value from the form and update the ACF form "test_field".
$post_id = $_REQUEST["post_id"];
$userID = $_REQUEST('user_id');
$current_field = get_field('test_field', $userID);
update_field('test_field', $post_id, $userID);
if ($current_field === false) {
$result['type'] = 'error';
} else {
$result['type'] = 'success';
}
// Check if action was fired via Ajax call. If yes, JS code will be triggered, else the user is redirected to the post page
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$result = json_encode($result);
echo $result;
} else {
header("Location: " . $_SERVER['HTTP_REFERER']);
}
// don't forget to end your scripts with a die() function - very important
die();
}
// define the function to be fired for logged out users
function login_to_add_to_favorites() {
echo 'You must log in to like';
die();
}
// used here only for enabling syntax highlighting. Leave this out if it's already included in your plugin file.
// Fires after WordPress has finished loading, but before any headers are sent.
add_action( 'init', 'enqueue_add_dog_to_favorites_script' );
function enqueue_add_dog_to_favorites_script() {
// Register the JS file with a unique handle, file location, and an array of dependencies
wp_register_script( 'add_favorites_script', plugin_dir_url( __FILE__ ) . 'add_favorites_script.js', array('jquery') );
// localize the script to your domain name, so that you can reference the url to admin-ajax.php file easily
wp_localize_script( 'add_favorites_script', 'myAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
// enqueue jQuery library and the script you registered above
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'add_favorites_script' );
}
and my JS:
jQuery(document).ready( function() {
jQuery(".not-favorite").click( function(e) {
e.preventDefault();
post_id = jQuery(this).attr("data-post_id");
nonce = jQuery(this).attr("data-nonce");
user_id = jQuery(this).attr("data-user_id");
jQuery.ajax({
type : "post",
dataType : "json",
url : myAjax.ajaxurl,
data : {action: "add_dog_to_favorites", post_id : post_id, nonce: nonce, user_id : user_id},
success: function(response) {
if(response.type == "success") {
console.log('success!');
}
else {
alert("Your like could not be added");
}
}
});
});
});
I have a console.log('success!'); line that should trigger if successful, but it is not triggering. The failure alert is also not triggering, which leads me to believe the function is not running at all? I feel like it's pretty close to working, but just can't get there.
Any help would be greatly appreciated!
Update: Ok. I found that the function is actually exiting because of the nonce verification:
if (!wp_verify_nonce( $_REQUEST['nonce'], 'add_dog_to_favorites_nonce' )) {
exit('Woof Woof Woof');
}
I have tried commenting this block of code out to see what would happen and I get a critical error.
Update: Fixed an error in my code that allows it to work without the nonce check.
$userID = $_REQUEST('user_id'); needs to be $userID = $_REQUEST['user_id'];
I still will need to get the nonce check working, but progress is being made. If anyone knows why that is not working, that would wrap this up!
I have followed Matt Van Andel's Custom List Table Example to create an admin table which displays enquiries to a website via an external MySql database.
Having implemented the displaying of my data correctly, I have added a select box column which will allow the admin to update the 'status' of the enquiry (Awaiting Response, Responded etc.) and I need this to update my database via AJAX.
I need a change in these select boxes to trigger an AJAX call which will update the database with the new value but I seem to be struggling to link my external AJAX file to my plugins .php file correctly.
I have reached a point where (in the Network tab) I can see I am loading the .js file like so:
Code in list-table.php:
function ajax_test_enqueue_scripts() {
wp_enqueue_script( 'list-table', plugins_url( 'js/list-table.js', __FILE__ ), array('jquery'));
}
add_action( 'admin_enqueue_scripts', 'ajax_test_enqueue_scripts' );
And my AJAX:
jQuery('.status-select').on( 'change', function ajaxSubmit() {
alert("IT WORKED!");
$.ajax({
url: ajaxurl,
type: "POST",
cache: false,
data: this.val()
})
});
At the moment the file is showing but the 'on change' part doesn't seem to be firing (hence the 'alert' in the .js).
Apologies if this question is worded or organised poorly, it is my first time posting!
Hope someone can explain what/ where I am going wrong.
This is quite a specific requirement but for anyone else using custom tables in WordPress and wanting to update an external myqsl database via AJAX - here's how I did it.
The AJAX side of things -
<script>
jQuery('select.status').on('change', function() {
var $statusSelect = jQuery( this );
var $statusSelectCell = $statusSelect.parent();
var enquiryStatusValue = $statusSelect.val();
var currentBackgroundColor = $statusSelectCell.parent().css("backgroundColor");
var ajaxData = {
'action': 'update_status_db',
'currentId': $statusSelect.attr('id'),
'data': enquiryStatusValue
}
jQuery.ajax({
type: "POST",
url: "/wp-admin/admin-ajax.php",
data: ajaxData,
success: function( response ) {
console.log("Data returned: " + response );
$statusSelectCell.parent().css({"background-color": "#b3e6b3"});
$statusSelectCell.parent().animate({backgroundColor: currentBackgroundColor}, 1200);
},
error: function() {
alert("FAILED TO POST DATA!!");
}
});
})
</script>
Note, the users success confirmation in this case is for the specific row to flash green. This is optional.
Next, the PHP to process the AJAX request. This is to be written outside the tables class.
wp_enqueue_script('jquery');
add_action( 'wp_ajax_update_status_db', 'update_status_db_callback' );
function update_status_db_callback(){
global $wpdb;
$newStatus = $_POST['data'];
$currentId = $_POST['currentId'];
$table = 'wp_enquiryinfo';
$result = $wpdb->update( $table, array( 'status' => $newStatus ), array( 'id' => $currentId ));
echo $_POST['data'];
if (!$result) {
echo "FAILED TO UPDATE";
} else {
$result;
echo "WILL UPDATE SUCCESSFULLY - CALL RESULT FUNCTION";
};
wp_die();
}
Here are a couple of the things I was getting wrong originally:
Firstly, the callback function HAS to end with _callback. Secondly, I didn't call the wp_die function at the end of this - this again is required.
Hopefully this may be of use to someone in the future.
i have following code
ajax
//ajax edit button
$('.edit_button').on('click', function(e) {
e.preventDefault();
var id_produk = $(this).attr('id');
$.ajax({
type : "POST",
url : "editproduk",
data : id_produk,
dataType: 'JSON',
success : function(data) {
alert('Success');
console.log(data);
},
error: alert('Errors')
});
});
i always get messagebox error
and don't know where i'm missing,
because in chrome - inspect element - console not give any clue
my route
Route::post('/account/editproduk', array(
'as' => 'edit-produk-post',
'uses' => 'AccountController#postEditProduk'
));
my controller
public function postEditProduk() {
if (Request::ajax()) {
return "test test";
}
}
extended question
i running my script well after using return Response::json() like this
$id_produk = Input::get('id_produk');
$produk = Produk::findOrFail($id_produk);
return Response::json($produk);
and access it in view by this script
success : function(data) {
alert('Success');
console.log(data["name-produk"]);
}
but if i want to return array json like
$id_produk = Input::get('id_produk');
$produk = Produk::findOrFail($id_produk);
$spesifikasi = SpesifikasiProduk::where('id_produk', '=', $id_produk);
return Response::json(array($produk, $spesifikasi));
i can't access it in view like this...
success : function(data1, data2) {
alert('Success');
console.log(data1["name-produk"] - data2["title-spek"]);
}
how to access json array
extended question update
if i'm wrong please correct my script
because i get a litle confused with explenation
is this correct way to return it?
Response::json(array('myproduk' => 'Sproduk', 'data2' => 'testData2'));
result
console.log(produk["myproduk"]);
--------------------------------
Object {id_produk: 1, nama_produk: "produk1", deskripsi: "desc_produk"
console.log(produk["data2"]);
--------------------------------
testData2
and i still don't have idea how to print nama_produk in my_produkarray
Question 1:
Why is this code not sending JSON data back.
public function postEditProduk() {
if (Request::ajax()) {
return "test test";
}
}
Answer: Because this is not the right way to send the JSON data back.
From the Laravel 4 docs, the right way to send JSON data back is linked. Hence the correct code becomes:
public function postEditProduk() {
if (Request::ajax()) {
return Response::json("test test");
}
}
Question 2:
Why am I not able to access the data in data1 and data2
success : function(data1, data2) {
alert('Success');
console.log(data1["name-produk"] - data2["title-spek"]);
}
Answer: Because this is not the right way to catch the JSON data. The right way to send is given in the Laravel 4 API reference docs.
static JsonResponse json(string|array $data = array(), int $status = 200, array $headers = array(), int $options)
As you can see the method json takes string or array as the first parameter. So you need to send all your data in the first parameter itself (which you are doing). Since you passed only one parameter, you have to catch only 1 parameter in your javascript. You are catching 2 parameters.
Depending on what $produk and $spesifikasi is, your data will be present in one single array. Lets say that $produk is a string and $spesifikasi is an array. Then your data on the javascript side will be this:
[
[0] => 'value of $produk',
[1] => array [
[0] => 'value1',
[1] => 'value2'
]
]
It would be best if you print the log your entire data and know the structure. Change your code to this:
success : function(data) {
console.log(data.toString());
}
This will print your entire data and then you can see the structure of your data and access it accordingly. If you need help with printing the data on your console, google it, or just let me know.
I sincerely hope that I have explained your doubts clearly. Have a nice day.
Edit
extended question answer:
Replace this line:
$spesifikasi = SpesifikasiProduk::where('id_produk', '=', $id_produk);
With this:
$spesifikasi = SpesifikasiProduk::where('id_produk', '=', $id_produk)->get();
Without calling the get() method, laravel will not return any value.
Then access your data in javascript like this:
console.log(JSON.stringify(data));
This way you will get to know the structure of your data and you can access it like:
data[0]["some_key"]["some_other_key"];
In your controller you're returning text while your ajax request awaits json data, look at these lines of codes, I think you should get your answer:
if(Request::ajax()) {
$province = Input::get('selectedProvince');
//Get all cites for a province
if ($cityList = City::where('province_id','=', $province)) {
return Response::make($cityList->get(['id', 'name']));
}
return Response::json(array('success' => false), 400);
}
how do I do two xhr.gets one after the other using dojo ?
I have ....
require(["dojo/_base/xhr", "dojo/dom", "dojo/domReady!"],
function(xhr, dom) {
// Using xhr.get, as very little information is being sent
xhr.get({
// The URL of the request
url: "inc/etl2json.php?item=Execs",
// The success callback with result from server
load: function(execContent) {
dom.byId("Execs").innerHTML = execContent;
},
// The error handler
error: function() {
// Do nothing -- keep old content there
}
});
});
I would like to do another xhr.get to "inc/etl2json.php?item=Execs" and assign it to dom.byId("Elapsed").innerHTML = elapsedContent;
just call again xhr.get() inside the load function, well that if the content is supposed to change, else you could just use the same data retrieved the first time:
xhr.get({
load:function(data){
//use the first data you retrieved
xhr.get({
load: function(data2){
//do what you like with the nuew data
}
});
}
});
Although nesting is a straightforward solution it almost always leads to unreadable code, so I would do the same as #Ricardo did, but use the advantage of Dojo's Deferred (+ here) and employ chaining:
var requestUrl = "inc/etl2json.php?item=Execs";
xhr.get({ url: requestUrl})
.then(function(results) {
dom.byId("execs").innerHTML = results;
})
.then(function(results) {
return xhr.get({ url: requestUrl});
})
.then(function(results) {
dom.byId("elapsed").innerHTML = results;
})
See it in action at jsFiddle: http://jsfiddle.net/phusick/73X88/
I think you should add another xhr call for the elapsedContent. I don't see any relation between the two calls so you should make them separate. Nesting one in another is not necessary.
just add
xhr.get({
// The URL of the request
url: "inc/etl2json.php?item=Execs",
// The success callback with result from server
load: function(elapsedContent) {
dom.byId("Elapsed").innerHTML = elapsedContent;
},
// The error handler
error: function() {
// Do nothing -- keep old content there
}
});
I'm wondering what is the best method to handle AJAX calls with jQuery? Right now I'm doing something like following:
$("#test").live('click', function(){
// Process form
$.ajax({
type: "post",
url: "test.php",
success: function(html){
if(html.success == 0) {
alert('Error');
} else {
var obj = $.parseJSON(html.rows);
$("#success").html(obj[0].name);
}
},
dataType:'json'
});
return false;
});
In test.php file, I'm checking if request is an AJAX request. If it's an AJAX request I'm running a database query to get some data (this part isn't important in this question, I think):
// query goes here
if(mysql_num_rows($query) > 0 ) {
$result['success'] = 1;
$result['data'] = json_encode($data);
} else {
$result['success'] = 0;
}
Now I'm wondering if my method is the best possible? FYI I'm using KohanaPHP framework currently, so I want to not break MVC "rules". If I'm doing it wrong, do you have any tips and suggestions how to handle AJAX calls in controllers?
Regards,
Tom
What you have looks good here, though I don't think you need a $.parseJSON() there, it should already be an object at that point, this should work:
$("#success").html(html.rows[0].name);
As a side note, from a readability/maintainability perspective, I'd rename your html argument to be data, like this:
success: function(data) {
This is purely preference, but using html when it's an HTML type response, and data or something else when it's JSON/already an object you're expecting keeps things a bit easier to read for outsiders.
#tom - you need to encode the PHP array like this:
$data = array(
'status' => 'success'
);
echo json_encode($data);
But you might want to change the array structure a little. Since the xhr object has a text status I usually encode an JSON array like this:
$response = array(
'status' => 'success' // or flash or error
,'flash' => array(
'header' => 'whatever is wrong with submission of data html list format'
'fields' => array('field names to be highlighted')
)
,'html' => 'html presentation'
,'data => array('json data')
);
echo json_encode($response);
Now you can do some nice things like this:
,success: function(response) {
if (response.status === 'success') {
$('.basic_container').hide();
that.removeDataTable();
that.getContent(contentUrl);
$('.basic_container').show();
}
if (response.status === 'flash') {
$('#flash').html(response.flash.header);
$('#flash').show();
that.highlightWithFlash(response.flash.fields);
}
}