I am new to Stackoverflow and relatively new to WordPress as well. I have been trying to build a custom WordPress theme that also allows you to insert images for categories in the WordPress Dashboard. So far, I have been able to get the image URL saved into the database using the following code:
update_term_meta($term_id, 'custom_image_data', $image_data);
($image_data is an array with the elements: ID, and URL for the image)
However, now I would like to retrieve these two pieces of information and share them with my coresponding Javascript file. So far I have this code:
function image_uploader_js() {
wp_register_script('image_file_uploader_js', get_template_directory_uri() . '/js/image_uploader.js', array('jquery', 'media-upload'));
wp_enqueue_script('image_file_uploader_js');
wp_localize_script('image_file_uploader_js', 'customUploads', array('imageData' => get_term_meta(get_queried_object_id(), 'custom_image_data', true)) ); //**
}
add_action('admin_footer', 'image_uploader_js');
However, when I go into the Google Chrome console and type in CustomUploads it just shows an empty string. But if I were to replace the code get_queried_object_id() with a static number 1 (which corresponds to the $term_id of the category) I get CustomUploads { id: ##, URL: HTTPS://..... } which is the desired result.
My question is why doesn't the original code work and how would I be able to share the id and URL or my category image with my Javascript file?
Make sure that you are on the category page then get_queried_object_id() will return term id. in other pages you will get a different id corresponding to that page.
You can use is_category() to check whether you are on the category page.
function image_uploader_js() {
if( is_category() ){
wp_register_script('image_file_uploader_js', get_template_directory_uri() . '/js/image_uploader.js', array('jquery', 'media-upload'));
wp_enqueue_script('image_file_uploader_js');
wp_localize_script('image_file_uploader_js', 'customUploads', array('imageData' => get_term_meta(get_queried_object_id(), 'custom_image_data', true)) ); //**
}
}
add_action('admin_footer', 'image_uploader_js');
Or you can get all terms and push to an array and then you can access to js file.
function image_uploader_js() {
$category = get_terms( array(
'taxonomy' => 'category', // your custom taxonomy name
'hide_empty' => false
) );
$imageData = array();
if( !empty( $category ) ){
foreach ( $category as $key => $cat ) {
$imageData[$cat->term_id] = get_term_meta( $cat->term_id, 'custom_image_data', true );
}
}
wp_register_script( 'image_file_uploader_js', get_template_directory_uri() . '/js/image_uploader.js', array('jquery', 'media-upload') );
wp_enqueue_script( 'image_file_uploader_js');
wp_localize_script( 'image_file_uploader_js', 'customUploads', array( 'imageData' => $imageData ) ); //**
}
add_action('admin_footer', 'image_uploader_js');
Related
I am new to wordpress and I need to call a php function from ajax but my code is not working. I was reading about the ajax standard in wordpress, but I don't know what happens, I have followed several tutorials and answers in this blog and they all talk about the action to enqueue the javascript file, but the problem continues and I don't know what I'm doing wrong. To continue I share my code.
This is my function to enqueue my javascript file:
function enqueue_script() {
$ajax_script = 'popup';
$uri = get_stylesheet_directory_uri() . '/assets/front/js/popup.js';
wp_register_script($ajax_script, $uri);
wp_localize_script( $ajax_script, 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
wp_enqueue_script( $ajax_script, $uri, array('jquery'), rand(111,9999), 'all');
}
add_action( 'wp_enqueue_scripts', 'enqueue_script' );
My php function to call, this is in an update_request_status.php file:
function update_status(){
echo "<script>alert('I am update function!!!!');</script>";
}
This is my js action, :
$('.btn-confirm').click(function(){
var url_string = window.location.href;
var url = new URL(url_string);
var request_id = url.searchParams.get("request_id");
$.ajax({
url: ajax_object.ajaxurl,
type: 'POST',
cache: false,
data: { "request_id": request_id } + '&action=change_status',
success:function(data){
alert("YEs I doing");
},
error:function(){
alert("¡Error en el servidor, contancte al administrador!");
}
});
window.location.href = "http://localhost:8081/megafrescos/pendientes";
$('#msg-remove-request').css('display', 'none');
});
And finally, this is my modal with the button that triggers the action to call my php function:
<div class="warning-msg" id="msg-remove-request">
<button class="btn-close" id="btn-close">×</button>
<h5>¿Dar por concluida esta solicitud ? </h5><hr>
<?php echo fix_request()?>
<div class="confirm-btns">
<button class="btn-confirm">Aceptar</button>
<button class="btn-close">Cancelar</button>
</div>
<div class='update-status'></div>
</div>
Can somebody help me?
There are multiple ways to do it. First I'll show the one you were working on.
You'll need to define two actions with wp_ajax_{action} and wp_ajax_nopriv_{action}, where {action} is a placeholder for a keyword to identify the function that needs to be called. The former is only works when users are logged in. The latter is for request from unauthenticated users.
Both hooks should refer to the same function that you are trying to call.
The example below returns either the request_id that has been sent or a string with 'Nothing' as a response, just to test things out.
add_action( 'wp_ajax_nopriv_update_status', 'update_status' ) ;
add_action( 'wp_ajax_update_status', 'update_status' );
function update_status() {
$request_id = isset( $_POST[ 'request_id' ) ) ?
$_POST[ 'request_id' ) :
'Nothing';
echo $request_id;
}
The other, and more modern approach is using the REST API. This enables you to create an endpoint where you get more controls over de URL and sanitizing.
Your endpoint would look something like this
https://yourwebsite.com/wp-json/api/v1/update. You can get the static URL to the REST endpoint by using get_rest_url(), like you did with admin_url( 'admin-ajax.php' ) and should add that to your wp_localize_script function in the enqueue file.
The endpoint checks the methods allowed and calls the callback specified in the options array. From there you can access the $request object which contains info like the given arguments from your request.
Then return a response to read on the frontend.
add_action( 'rest_api_init', 'register_update_endpoint' );
function register_update_endpoint() {
// Register new route to get data from
register_rest_route( 'api/v1', // Mandatory prefix with version
'/update/', // Name of the route, can be anything.
array(
'methods' => array( 'POST' ), // Allowed methods.
'callback' => 'update_status' // Function to call when URL is called.
)
);
function update_status( WP_REST_Request $request ) {
$request_id = $request->has_param( 'request_id' ) ?
$request->get_param( 'request_id' ) :
'Nothing';
$response = new WP_REST_Response( $request_id; );
return $request_id;
}
}
I have a wordpress app locally setup in my computer. In the wordpress admin i have a Countries tab under the Posts. I'll attach an image for better understanding.
I want to write a function to get the country values for my front-end. For that i have written a function like this
public function get_destinations()
{
$bookings = get_posts(
array(
'taxonomy'=> 'country',
'numberposts' => -1,
)
);
return $bookings;
}
But for some reason this function returns all the posts in the database. I want to get only the country names.
i found the taxonomy from my local url which is
http://localhost/my_project/wp-admin/edit-tags.php?taxonomy=country
I'm very new to wordpress and dont have a clue on how to retrieve these data to my front end. What am i doing wrong here?
If you want to show the only category or taxonomy name instead of get_posts you have to use get_terms
check this code.
// Get the taxonomy's terms
$terms = get_terms(
array(
'taxonomy' => 'country',
'hide_empty' => false, // show category even if dont have any post.
)
);
// Check if any term exists
if ( ! empty( $terms ) && is_array( $terms ) ) {
// Run a loop and print them all
foreach ( $terms as $term ) { ?>
<a href="<?php echo esc_url( get_term_link( $term ) ) ?>">
<?php echo $term->name; ?>
</a><?php
}
}
-- Edit 1 --
Found out some new things. I'm adding them on top since they might be more relevant than the code below.
I've rerun the scripts a few times. I now get different findings actually.
Running var_dump($wp_query->query); right after $the_query = new WP_Query($queryArgs);In the first render of the post loop gives me the query vars of the page the loop is rendered on. Calling it with ajax it reruns the same part of the code, right? So than it returns empty.
My thoughts:
Pages is called, runs funtions.php.
Runs the part of the wp_enqueue_script('rtt_scripts');
This is the moment it gets the current $wp_query values. Which are the values of the page.
Than renders the page with the post loop.
This is the moment the post loop runs $the_query = new WP_Query($queryArgs);
On press of the load more the ajax than calls it to rerun the post loop. With the query vars set with wp_enqueue_script('rtt_scripts');
This made me think. Am I running the code in a wrong order? Are the query vars for ajax set on the wrong moment? Other thought. Should I focus on how to get the query vars on the first post loop to the ajax query vars?
-- End Edit --
I’m having trouble with a load more button in Wordpress. The code below is the basic code I have right now.
As far as I can see this should be a working code :) Problem is though that this doesn’t work.
My problem is that I don’t know where to start debugging. Closest I know where the problem lies is this:
In rtt_loadmore_ajax_handler() there is the var $queryArg
When var_dumping the var $queryArg in both rtt_post_grid() and rtt_loadmore_ajax_handler()
It gives different results. Here I would expect the same results. In the Ajax call it returns the arguments
of the current rendered page and not of the post query on this page.
Would the global $wp_query; be the problem? And how do I go from here?
The basic post code:
function rtt_post_grid()
{
$queryArgs = Array(
"post_type" => Array(
'news',
'agenda'
),
'posts_per_page' => 4,
'post_status' => 'publish',
'paged' => 1
);
// post grid wrap
echo '<div id="rtt_posts_wrap" >';
rtt_post_grid_query($queryArgs);
echo '</div>';
// load more button
echo '<form>';
echo '<button id="rtt_loadmore" class=" button">Load more post</button> ';
echo '<input type="hidden" name="action" value="loadmore" />'; // this line might be obsolete
echo '</form>';
}
function rtt_post_grid_query($queryArgs)
{
// The Query
$the_query = new WP_Query($queryArgs);
// The Loop
if ($the_query->have_posts()) {
echo '<ul>';
while ($the_query->have_posts()) {
$the_query->the_post();
echo '<li>' . get_the_title() . '</li>';
}
echo '</ul>';
/* Restore original Post Data */
wp_reset_postdata();
} else {
// no posts found
echo 'no posts found';
}
}
Setting the JS:
if(!has_action('rtt_post_grid_script_and_styles')) {
add_action('wp_enqueue_scripts', 'rtt_post_grid_script_and_styles', 1);
function rtt_post_grid_script_and_styles()
{
global $wp_query;
wp_register_script('rtt_scripts', plugin_dir_url( __FILE__ ) . 'js/script.js', array('jquery'), time());
wp_enqueue_script('rtt_scripts');
wp_localize_script('rtt_scripts', 'rtt_loadmore_params', array(
'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX
'posts' => json_encode($wp_query->query_vars), // everything about your loop is here
'current_page' => $wp_query->query_vars['paged'] ? $wp_query->query_vars['paged'] : 1,
'max_page' => $wp_query->max_num_pages
));
wp_enqueue_script('rtt_scripts');
}
}
The JS/Ajax:
jQuery(function($){
$(window).ready(function() {
$('#rtt_loadmore').click(function () {
$.ajax({
url: rtt_loadmore_params.ajaxurl,
data: {
'action': 'loadmore', // the parameter for admin-ajax.php
'query': rtt_loadmore_params.posts, // loop parameters passed by wp_localize_script()
'page': rtt_loadmore_params.current_page, // current page
},
dataType: 'json',
type: 'POST',
beforeSend: function (xhr) {
$('#rtt_loadmore').text('Bezig met laden...'); // some type of preloader
},
success: function (data) {
if (data) {
$('#rtt_loadmore').text('More posts');
$('#rtt_posts_wrap').append(data.content); // insert new posts
rtt_loadmore_params.current_page++;
if (rtt_loadmore_params.current_page == rtt_loadmore_params.max_page){
$('#rtt_loadmore').hide(); // if last page, HIDE the button
}
} else {
$('#rtt_loadmore').hide(); // if no data, HIDE the button as well
}
}
});
return false;
});
});
});
The Ajax handler:
add_action('wp_ajax_loadmore', 'rtt_loadmore_ajax_handler'); // wp_ajax_{action}
add_action('wp_ajax_nopriv_loadmore', 'rtt_loadmore_ajax_handler'); // wp_ajax_nopriv_{action}
function rtt_loadmore_ajax_handler(){
$postData = $_POST;
// prepare our arguments for the query
$queryArgs = json_decode( stripslashes( $postData['query'] ), true );
$queryArgs['paged'] = $postData['page'] + 1; // we need next page to be loaded
$queryArgs['post_status'] = 'publish';
ob_start();
rtt_post_grid_query($queryArgs);
$output = ob_get_contents();
ob_end_clean();
global $the_query;
echo json_encode( array(
'posts' => serialize( $the_query->query_vars ),
'max_page' => $the_query->max_num_pages,
'found_posts' => $the_query->found_posts,
'content' => $output
) );
die;
}
So, I've figured it out. I'll explain for it might be useful to somebody else.
The reason it did not work is because the code above is more useful in a template. But I use it in a shortcode. The wp_localize_script() was run on rendering the page and not on running the shortcode. That's why it didn't had the right variables.
I've moved the code below inside the shortcode. Right after the new WP_query:
// The Query
$the_query = new WP_Query($queryArgs);
// The Loop
if ($the_query->have_posts()) {
wp_enqueue_script_ajax_vars($the_query);
Than passed the new query
function wp_enqueue_script_ajax_vars($the_query)
{
wp_register_script('rtt_scripts', plugin_dir_url(__FILE__) . 'js/script.js', array('jquery'), time());
wp_localize_script('rtt_scripts', 'rtt_loadmore_params', array(
'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX
'posts' => json_encode($the_query->query_vars), // everything about your loop is here
'query_vars' => json_encode($the_query->query),
'current_page' => $the_query->query_vars['paged'] ? $the_query->query_vars['paged'] : 1,
'max_page' => $the_query->max_num_pages,
));
wp_enqueue_script('rtt_scripts', '', '', '', true); // note the last 'true' this sets it inside the footer
}
Resulting in wp_localize_script() creating the variable in the footer. It was in the header before. But by getting it within the shortcode, sending the new query arguments and putting them inside the footer (since the header is already rendered by then) I have set the JS var for Ajax.
Add the two order arguments to $queryArgs.
// prepare our arguments for the query
$queryArgs = json_decode( stripslashes( $postData['query'] ), true );
$queryArgs['paged'] = $postData['page'] + 1; // we need next page to be loaded
$queryArgs['post_status'] = 'publish';
$queryArgs['orderby'] = 'date'; // add this to order by date
$queryArgs['order'] = 'DESC'; // add this to display the most recent
Im trying to translate this string in javascript but i cant seem to do it properly.
$(".search-overlay .s").attr("placeholder", "Type here to search");
Ive tried the following but it gives errors, any ideas ?
$(".search-overlay .s").attr("placeholder", "<?php _e( '"Type here to search"', 'romeo' ); ?>");
Thanks.
You should do this proper Wordpress way by using wp_localize_script() function
Please check this codex page out:
https://codex.wordpress.org/Function_Reference/wp_localize_script
Basically in php:
// Register the script
wp_register_script( 'some_handle', 'path/to/myscript.js' );
// Localize the script with new data
$translation_array = array(
'some_string' => __( 'Some string to translate', 'plugin-domain' ),
'a_value' => '10'
);
wp_localize_script( 'some_handle', 'object_name', $translation_array );
// Enqueued script with localized data.
wp_enqueue_script( 'some_handle' );
And in javascript:
alert(object_name.some_string);
On my wordpress page, I have the following loop, which successfully outputs an attachment's caption.
<?php
$the_query = new WP_Query(array( 'post_type' => 'attachment'));
while ( $the_query->have_posts() ) : $the_query->the_post();
$attachment_data = wp_prepare_attachment_for_js();
echo '<h2>'.$attachment_data['caption'].'</h2>'
;?>
Now, I also need to call the attachment caption outside of the loop. This is what I'm trying in functions.php:
function custom_info()
{
global $wp_query;
$query_id = $wp_query->post->ID;
$attachment_data_query = wp_prepare_attachment_for_js( $query_id );
wp_register_script( 'custom_data_info');
$info = array(
'data_query' => $attachment_data_query['caption']
);
wp_enqueue_script( 'custom_data_info' );
wp_localize_script('custom_data_info', 'info', $info);
}
if ( !is_admin() ) add_action( "wp_enqueue_scripts", "custom_info", 10 );
And then it would be called in the external javascript file like so:
return info.data_query
I know the custom_info function and javascript file are talking with each other correctly. The problem is with how I am defining $query_id
EDIT: Almost fixed. The problem was that I didn't include a foreach statement, and so the first item in the loop was being repeated over and over again.
I've adjusted below, but for some reason, now the array is empty upon output of info.data_query...
function custom_info(){
global $wp_query;
wp_register_script( 'custom_data_info');
$info = array('data_query' => array());
foreach ( $wp_query->posts as $query_id) {
$attachment_data_query = wp_prepare_attachment_for_js( $query_id );
$info['data_query'][$query_id] = $attachment_data_query['caption'];
}
Are you sure $wp_query will return the correct post ID? In my experience, it's better to use global $post instead. Pass that into wp_prepare_attachment_js() instead:
global $post;
$post_id = $post->ID;
$attachment_data_query = wp_prepare_attachment_for_js( $post_id );