How can I activate Woocommerce Product Gallery in ajax container? - ajax

The new product gallery in Woocommerce is great, but unfortunately I can't get it to work outside the single product template page.
I'm using ajax to load in products in a container on my front page. The ajax call displays the product page: echo do_shortcode('[product_page id="' . $post_id . '"]');. The markup for the gallery is correct, but the .woocommerce-product-gallery container is marked with opacity: 0; and none of the scripts for the gallery is loaded.
How can I implement the gallery functionality with the ajax call and get it working?
Full ajax call:
JQuery
$('.product-modal-toggle').on('click',function(){
var theId = $(this).data('product-id');
var plagg = $(this).data('plagg');
var outfitEnkeltPlaggContainer = $('.outfit-enkelt-plagg');
var parentOutfit = $(this).closest('.outfit').attr('id');
var outfitDescendantContainer = $('#' + parentOutfit + ' .outfit-enkelt-plagg');
$.post('wp-admin/admin-ajax.php', {
action:'my_get_posts',
post_id: theId
}, function(data) {
console.log(data);
outfitDescendantContainer.html(data);
});
});
PHP
/*
** Get Woocommerce Products with Ajax.
** Display Product inside outfit container
*/
function my_get_posts_return() {
global $post;
$post_id = intval(isset($_POST['post_id']) ? $_POST['post_id'] : 0);
if ($post_id > 0) {
$the_query = new WP_query(array('p' => $post_id, 'post_type' => 'product'));
if ($the_query->have_posts()) {
while ($the_query->have_posts()) : $the_query->the_post();
$product = wc_get_product($post_id);
?>
<button class="close-plagg" type="button" name="close-plagg">
<img src="<?php echo get_template_directory_uri(); ?>/library/images/close.svg" alt="Close plagg">
</button>
<?php
echo do_shortcode('[product_page id="' . $post_id . '"]');
// wc_get_template_part( 'content', 'single-product' );
endwhile;
} else {
echo "There were no posts found";
}
}
wp_die();
}
add_action('wp_ajax_my_get_posts', 'my_get_posts_return');
add_action('wp_ajax_nopriv_my_get_posts', 'my_get_posts_return');

PHP
You have to enqueue the scripts of the gallery on your home page :
add_action( 'wp_enqueue_scripts', function(){
if( is_front_page() ){
wp_enqueue_script('zoom');
wp_enqueue_script('flexslider');
wp_enqueue_script('photoswipe-ui-default');
}
});
JS
In the success function of your $.postyou have to call the script :
$( '.woocommerce-product-gallery', data ).each( function() {
$( this ).wc_product_gallery();
} );
Hope this helps

Related

Ajax Load More Custom Post type WordPress

I am trying to load more post calling out the custom post type with the taxonomy array to sort out the specfic post or all Magazine port. If you click Load More and there is no post to return, the user will recieve a message. As of now when I click the "Load More" button, it seems like the funciton just loops with not returning 3 more post.
Below I have written up the steps I have taken to execute WordPress Ajax load more post functionality.
First Step:
Created a page template called taxonomy-magazine-category.php that lives in my theme folder with the markup to display 3 post and load more button functionality to return 3 more post at each click until all post are returned.
<div class="post row">
<?php
$paged = ( get_query_var('page') ) ? get_query_var('page') : 1;
$latests = new WP_Query(array(
'posts_per_page' => 3,
'post_type' => 'magazine',
));
while($latests->have_posts()): $latests->the_post(); //put the post card here ?>
<div class="col-12 col-sm-12 col-md-7 col-xl-9">
<div class="blog-article-cards list-articles">
<?php
get_template_part('/components/magazine-article-card', null, array( 'magazines' => $magazines[$i], 'style' => 'regular'));
?>
</div>
</div>
<?php endwhile; ?>
</div>
<script>
var limit = 3,
page = 1,
type = 'latest',
category = '',
max_pages_latest = <?php echo $latests->max_num_pages ?>
</script>
<?php if ( $latests->max_num_pages > 1 ){
echo '<div class="load_more text-center">
Load More
</div>';
} else { ?>
<article>
<h1>Sorry...</h1>
<p><?php _e('Sorry, No Posts Available !'); ?></p>
</article>
<?php } wp_reset_query(); ?>
<?php get_footer(); ?>
Second Step:
Developed the function filter snippet of script at the bottom of the functions.php file that lives in /themes/understrap-child. The top function loads the Ajax files in WordPress installation including the custom Ajax file I have created which is in step three. The second function retuns the the post from the ajax handler.
function bsubash_load_more_scripts() {
wp_enqueue_script('jquery');
wp_register_script( 'loadmore_script', get_stylesheet_directory_uri() . '/js/ajax.js', array('jquery') );
wp_localize_script( 'loadmore_script', 'loadmore_params', array(
'ajaxurl' => admin_url('admin-ajax.php'),
) );
wp_enqueue_script( 'loadmore_script' );
}
add_action( 'wp_enqueue_scripts','bsubash_load_more_scripts' );
function bsubash_loadmore_ajax_handler(){
$type = $_POST['type'];
$category = isset($_POST['category']) ? $_POST['category']: '';
$args['paged'] = $_POST['page'] + 1;
$args['post_status'] = 'publish';
$args['posts_per_page'] = $_POST['limit'];
if($type == 'archive'){
$args['category_name'] = $category;
}
query_posts( $args );
if( have_posts() ) :
while(have_posts()): the_post();
//write your single post card
the_title();
the_excerpt();
endwhile;
endif;
die;
}
add_action('wp_ajax_loadmore','bsubash_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmore','bsubash_loadmore_ajax_handler');
Final Step:
Created an ajax.js file that lives in my theme folder /js/ajax.js which you will see in the funciton at step two. The ajax will not return the post after you click load more including displaying loading and load more static messages. This seems to be working fine.
jQuery(function($) {
$('.btn-load-more').click(function(e) {
e.preventDefault();
var button = $(this),
data = {
'action': 'loadmore',
'limit': limit,
'page': page,
'type': type,
'category': category
};
$.ajax({
url: loadmore_params.ajaxurl,
data: data,
type: 'POST',
beforeSend: function(xhr) {
button.text('Loading...'); // change the button text, you can also add a preloader image
},
success: function(data) {
if (data) {
$(".latest_posts_wrapper").append(data);
page++;
button.text('Load More');
if (page == max_pages_latest)
button.remove(); // if last page, remove the button
} else {
button.remove(); // if no data, remove the button as well
}
}
});
});
});
All Done!!!
**
What is in my template file?**
Above, at the top of my page template, I have other post appearing that are featured post. These post are returning from the proxy. I am just pointing this out so you are aware of what is in my file as well. This isn't impacting my issue.
$magazines = [];
$wp_query = new WP_Query(
array(
'post_type' => 'Magazine',
'tax_query' => array(
array (
'taxonomy' => 'magazine_categories',
'field' => $categoryId,
'terms' => $category,
'posts_per_page' => $postsPerPage,
)
),
)
);
while ($wp_query->have_posts()) : $wp_query->the_post();
//$blogProxy = new BlogProxy(get_the_ID());
$magazine = new Magazine();
$magazine->title = get_the_title();
$magazine->featured_image = get_the_post_thumbnail_url(get_the_ID());
$magazine->preview_text = get_the_excerpt();
$magazine->permalink = get_the_permalink();
$magazine->date = get_the_date();
array_push($magazines, $magazine);
endwhile;
wp_reset_postdata();
?>
My goal is to develop a load more button with a custom post type using AJAX. If you follow the steps above you should see an active functionality that doesn't return post after clicking the load more button.
/* myloadmore.js */
jQuery(function($){ // use jQuery code inside this to avoid "$ is not defined" error
$('.misha_loadmore').click(function(){
var button = $(this),
data = {
'action': 'loadmore',
'query': misha_loadmore_params.posts, // that's how we get params from wp_localize_script() function
'page' : misha_loadmore_params.current_page
};
$.ajax({ // you can also use $.post here
url : misha_loadmore_params.ajaxurl, // AJAX handler
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
button.text('Loading...'); // change the button text, you can also add a preloader image
},
success : function( data ){
if( data ) {
button.text( 'More posts' ).prev().before(data); // insert new posts
misha_loadmore_params.current_page++;
if ( misha_loadmore_params.current_page == misha_loadmore_params.max_page )
button.remove(); // if last page, remove the button
// you can also fire the "post-load" event here if you use a plugin that requires it
// $( document.body ).trigger( 'post-load' );
} else {
button.remove(); // if no data, remove the button as well
}
}
});
});
});
/* To style the button the according way use CSS below. */
.misha_loadmore{
background-color: #ddd;
border-radius: 2px;
display: block;
text-align: center;
font-size: 14px;
font-size: 0.875rem;
font-weight: 800;
letter-spacing:1px;
cursor:pointer;
text-transform: uppercase;
padding: 10px 0;
transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out, color 0.3s ease-in-out;
}
.misha_loadmore:hover{
background-color: #767676;
color: #fff;
}
This is the AJAX handler function. Insert it to your functions.php file.
/* Enqueue jQuery and myloadmore.js. Pass query parameters to the script. */
function misha_my_load_more_scripts() {
global $wp_query;
// In most cases it is already included on the page and this line can be removed
wp_enqueue_script('jquery');
// register our main script but do not enqueue it yet
wp_register_script( 'my_loadmore', get_stylesheet_directory_uri() . '/myloadmore.js', array('jquery') );
// now the most interesting part
// we have to pass parameters to myloadmore.js script but we can get the parameters values only in PHP
// you can define variables directly in your HTML but I decided that the most proper way is wp_localize_script()
wp_localize_script( 'my_loadmore', 'misha_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' => get_query_var( 'paged' ) ? get_query_var('paged') : 1,
'max_page' => $wp_query->max_num_pages
) );
wp_enqueue_script( 'my_loadmore' );
}
add_action( 'wp_enqueue_scripts', 'misha_my_load_more_scripts' );
function misha_loadmore_ajax_handler(){
// prepare our arguments for the query
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // we need next page to be loaded
$args['post_status'] = 'publish';
// it is always better to use WP_Query but not here
query_posts( $args );
if( have_posts() ) :
// run the loop
while( have_posts() ): the_post();
// look into your theme code how the posts are inserted, but you can use your own HTML of course
// do you remember? - my example is adapted for Twenty Seventeen theme
get_template_part( 'template-parts/post/content', get_post_format() );
// for the test purposes comment the line above and uncomment the below one
// the_title();
endwhile;
endif;
die; // here we exit the script and even no wp_reset_query() required!
}
add_action('wp_ajax_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_{action}
add_action('wp_ajax_nopriv_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_nopriv_{action}

Woocommerce how to ajaxify add to cart button for variable products using custom html radio buttons instead of dropdown menu - no plugin

I'm trying to put all of the pieces of this puzzle together. I've been reading all of the questions and answers on this subject for the past 3 days. So the general blueprint that i'm following is as follows:
On single product page, first checking whether the type of product is "simple" or "variable".
If product is "variable" then i'm using woocommerce_variable_add_to_cart(); function to output the proper html.
Then trying to generate new and custom html (i.e "radio buttons") using the defualt html (i.e "dropdown menu") and woocommerce hooks.
Then trying to give functionality to the new and custom html (i.e "radio buttons") using javascript.
Then hiding the default dropdown menu using css.
Then trying to send an ajax request to the wordpress.
Then trying to process that ajax request on the backend and add the product to the cart.
Here is my code for each section:
Checking whether the type of product is "variable" on the single product page:
global $post;
$product = wc_get_product($post->ID);
$product_type = $product->get_type();
If the product type is "variable" then output the proper html:
if($product_type == 'variable'):
woocommerce_variable_add_to_cart();
endif;
Generating new and custom html (radio buttons) using php and woocommerce hooks:
add_filter('woocommerce_dropdown_variation_attribute_options_html', 'my_theme_variation_radio_buttons', 20, 2);
function my_theme_variation_radio_buttons($html, $args)
{
$args = wp_parse_args(apply_filters('woocommerce_dropdown_variation_attribute_options_args', $args), array(
'options' => false,
'attribute' => false,
'product' => false,
'selected' => false,
'name' => '',
'id' => '',
'class' => '',
'show_option_none' => __('Choose an option', 'woocommerce'),
));
if (false === $args['selected'] && $args['attribute'] && $args['product'] instanceof WC_Product) {
$selected_key = 'attribute_' . sanitize_title($args['attribute']);
$args['selected'] = isset($_REQUEST[$selected_key]) ? wc_clean(wp_unslash($_REQUEST[$selected_key])) : $args['product']->get_variation_default_attribute($args['attribute']);
}
$options = $args['options'];
$product = $args['product'];
$attribute = $args['attribute'];
$name = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title($attribute);
$id = $args['id'] ? $args['id'] : sanitize_title($attribute);
$class = $args['class'];
$show_option_none = (bool)$args['show_option_none'];
$show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __('Choose an option', 'woocommerce');
if (empty($options) && !empty($product) && !empty($attribute)) {
$attributes = $product->get_variation_attributes();
$options = $attributes[$attribute];
}
$radios = '<div class="variation-radios">';
if (!empty($options)) {
if ($product && taxonomy_exists($attribute)) {
$terms = wc_get_product_terms($product->get_id(), $attribute, array(
'fields' => 'all',
));
foreach ($terms as $term) {
if (in_array($term->slug, $options, true)) {
$id = $name . '-' . $term->slug;
$radios .= '<input type="radio" data-checked="no" id="' . esc_attr($id) . '" name="' . esc_attr($name) . '" value="' . esc_attr($term->slug) . '" ' . checked(sanitize_title($args['selected']), $term->slug, false) . '><label for="' . esc_attr($id) . '">' . esc_html(apply_filters('woocommerce_variation_option_name', $term->name)) . '</label>';
}
}
} else {
foreach ($options as $option) {
$id = $name . '-' . $option;
$checked = sanitize_title($args['selected']) === $args['selected'] ? checked($args['selected'], sanitize_title($option), false) : checked($args['selected'], $option, false);
$radios .= '<input type="radio" id="' . esc_attr($id) . '" name="' . esc_attr($name) . '" value="' . esc_attr($option) . '" id="' . sanitize_title($option) . '" ' . $checked . '><label for="' . esc_attr($id) . '">' . esc_html(apply_filters('woocommerce_variation_option_name', $option)) . '</label>';
}
}
}
$radios .= '</div>';
return $html . $radios;
}
add_filter('woocommerce_variation_is_active', 'my_theme_variation_check', 10, 2);
function my_theme_variation_check($active, $variation)
{
if (!$variation->is_in_stock() && !$variation->backorders_allowed()) {
return false;
}
return $active;
}
Giving functionality to "radio buttons" using javascript:
jQuery(document).ready($ => {
$(document).on('change', '.variation-radio input', function () {
$('.variation-radio input:checked').each(function (index, element) {
var radioElement = $(element);
var radioName = radioElement.attr('name');
var radioValue = radioElement.attr('value');
$('select[name="' + radioName + '"]').val(radioValue).trigger('change');
});
});
$(document).on('woocommerce_update_variation_values', function () {
$('.variation-radio input').each(function (index, element) {
var radioElement = $(element);
var radioName = radioElement.attr('name');
var radioValue = radioElement.attr('value');
radioElement.removeAttr('disabled');
if ($('select[name="' + radioName + '"] option[value="' + radioValue + '"]').is(':disabled')) {
radioElement.prop('disabled', true);
}
});
});
$("a.reset_variations").click(function () {
$('input:radio[name="attribute_size"]').prop('checked', false); $(this).css('display', 'none');
});
})
Hiding the default dropdown menu using css:
table.variations select{
display: none;
}
Sending an ajax request to the wordpress:
jQuery(document).ready($ => {
$("button.single_add_to_cart_button").on('click', function (e) {
e.preventDefault();
var myBtn = $(this),
$form = myBtn.closest('form.variations_form'),
product_qty = $form.find('input[name=quantity]').val() || 1,
product_id = $form.find('input[name=product_id]').val(),
variation_id = $form.find('input[name=variation_id]').val() || 0,
variation = {},
keys = [],
values = [];
// Looping through the attributes names and save them as the keys array
$('table tr td.label label').each(function (index, element) {
let radioElement = $(element);
keys[index] = radioElement.text();
});
// Looping through the attributes values and save them as the values array
$('.variation-radios input:checked').each(function (index, element) {
let radioElement = $(element);
values[index] = radioElement.val();
});
// Looping through the variation object and save keys and values in that object
$.each(keys, function (index, element) {
variation[element] = values[index]
})
console.log(variation);
var data = {
action: 'woocommerce_add_variation_to_cart',
product_id: product_id,
quantity: product_qty,
variation_id: variation_id,
var: variation
};
$(document.body).trigger('adding_to_cart', [myBtn, data]);
$.ajax({
type: 'post',
url: wc_add_to_cart_params.ajax_url,
data: data,
beforeSend: function (response) {
myBtn.removeClass('added').addClass('loading');
},
complete: function (response) {
myBtn.addClass('added').removeClass('loading');
},
success: function (response) {
console.log(response);
if (response.error && response.product_url) {
window.location = response.product_url;
return;
} else {
$(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, myBtn]);
}
},
});
return false;
});
})
Processing the ajax request on the backend and add the product to the cart:
add_action('wp_ajax_nopriv_woocommerce_add_variation_to_cart', 'my_theme_testing_add_to_cart_variable');
add_action('wp_ajax_woocommerce_add_variation_to_cart', 'my_theme_testing_add_to_cart_variable');
function my_theme_testing_add_to_cart_variable()
{
if (isset($_POST['product_id']) && $_POST['product_id'] > 0) {
$product_id = apply_filters('woocommerce_add_to_cart_product_id', absint($_POST['product_id']));
$quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount($_POST['quantity']);
$variation_id = isset($_POST['variation_id']) ? absint($_POST['variation_id']) : '';
$attributes = explode(',', $_POST['var']);
$variation = array();
foreach ($attributes as $values) {
$values = explode(':', $values);
$variation['attributes_' . $values[0]] = $values[1];
}
$passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity);
if ($passed_validation && WC()->cart->add_to_cart($product_id, $quantity, $variation_id, $variation)) {
do_action('woocommerce_ajax_added_to_cart', $product_id);
if (get_option('woocommerce_cart_redirect_after_add') == 'yes') {
wc_add_to_cart_message($product_id);
}
WC_AJAX::get_refreshed_fragments();
} else {
$data = array(
'error' => true,
'product_url' => apply_filters('woocommerce_cart_redirect_after_error', get_permalink($product_id), $product_id)
);
wp_send_json($data);
}
die();
}
}
PROBLEM
Everything works until step 7 with no error but when i run the whole thing, the single product page refreshes and variable product doesn't get added to the cart. And the wordpress error says "{your attribute field} is a required field"!
I think the bug could be somewhere in the ajax call when i'm trying to send variation object to the backend.
Although, i get the data absolutely fine on the backend but it doesn't add it to the cart.
Things that i've tried to debug it
I've tried to send the data in the ajax call as an array but didn't work either.
I also tried to explode the variation data using both = and : but none has worked!
Hooof! It's been a long week so far :\ full of debugging, headaches and frustrations. Now when i try to run the whole shebang, i can't get it to work and i've been reading all of the Qs and As on SO but can't find the bug! I think i've been overthinking it for a couple of days and also there are lots of pieces to it.
So i think i need some extra pairs of eyes to hopefully detect the bug.
Thank you, i appreciate any insight(s)!
In addition, huge shout out to these fellows whom i've learned a lot from:
LoicTheAztec for this great answer and this and this and many more.
cfx for this great answer
Anthony Grist for this answer
helgatheviking for this answer
AND OTHERS
EDIT
The code works fine, bug wasn't in the code, it was in the data that i was provided with. I'll leave the code here just in case somebody needs it in the future.
Short ansewer
The code works fine, i'll leave it here just in case somebody needs it in the future. Bug wasn't in the code, it was in the data that i was provided with.
Detailed Explanation
The code works fine. The data that i was provided with was manipulated for some reasons by my client so that each variable product wasn't a real variable product but at the same time the labels were typed in as variable products (yea i know it's confusing and not a standard practice), that's why whenever i tried to add them to cart, it would give the error saying {your-attribute} is a required field.
So we deleted each product data and add it back as a real and true variable product, then the code worked without us changing anything in it.
Take-away
So remember, whenever developing your app, there are always two sides to this coin! One side is your code and the other side is the data you're working on.
So, always always always, make sure the data you're working with is the way/format it's supposed to be. Also if you can't find any bug in your code, remember to check/debug the other side which is the data.
If you don't check the data first or at any debugging stage, then it'll be hard to track down the issue down the road!
This bug created a long delay in the project (about 2 weeks until we tracked down the bug in the data). So make sure to always check the both sides of the coin:
First, the data you're working with
Second, the code you wrote.

How to add numeric pagination to Ajax result, that shows podcasts(custom post) filter by custom taxonomies

i would like to add numeric pagination (and load the posts dynamically) to this page, called 'page-podcast', where i filter, with Ajax call, my podcast (custom post), using these tags, genre, country and type: https://imgur.com/Qw8JOlC.
In my front end, page-podcast.php, i have this div, where post appears:
<div id="datafetch">Search results will appear here</div>
And in page function.php i added the function that call Ajax
add_action( 'wp_footer', 'ajax_fetch' );
function ajax_fetch() {
?>
<script type="text/javascript">
function fetch(e){
jQuery.ajax({
url: '<?php echo admin_url('admin-ajax.php'); ?>',
type: 'post',
data: { action: 'data_fetch', keyword: keywords},
success: function(data) {
jQuery('#datafetch').html( data );
}
});
}
</script>
The following code is the ajax function (always on function.php):
add_action('wp_ajax_data_fetch' , 'data_fetch');
add_action('wp_ajax_nopriv_data_fetch','data_fetch');
function data_fetch(){
...filter part, omitted, because it has nothing to do with the question...
$the_query = new WP_Query($query_args);
if( $the_query->have_posts() ) :
while( $the_query->have_posts() ): $the_query->the_post(); ?>
<h2><?php the_title();?></h2>
<?php endwhile;
else: ?>
<p class="no-criteria"><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p>
<?php
wp_reset_postdata();
endif;
die();
}
Someone has some tips/examples/code to share? Because i tried many solution that i find on the web, but nothing works.
Resolved.
So, i have added the number of the pages within the ajax function, before the end of the loop:
<?php if ($numberPages > 1): ?>
<ul>
<?php
for ($i = 1; $i <= $numberPages; $i++) {
echo '<li><a name="page" href="#" class="pagination" value="' . $i . '">'
. $i . '</a></li>';
}
?>
</ul>
$numberPages is equal to:
$the_query = new WP_Query($query_args);
$numberPages = $the_query->max_num_pages;
I create a global variable, call $page, set to 0.
Then i worked on my two event:
$(document).on("click touchend", ".premuto", function (event) {
event.preventDefault();
page = 1;
keywords['page'] = page;
keywords[$(this).attr('name')] = $(this).attr('value');
fetch(this);
});
$(document).on("click touchend", ".pagination", function (event) {
event.preventDefault();
keywords[$(this).attr('name')] = $(this).attr('value');
fetch(this);
});
".premuto" is an element that contain the id i want to pass to ajax (custom taxonomy) and page is set to 1.
".pagination" is the list of post's page number (1,2,...).
Finally, on my ajax function, i get the page number:
$paged = $_POST['keyword']['page'];
and in my wp_query i added:
'posts_per_page' => '2',
'paged' => $paged,

Ajax wipes value of session variable

I recently added an Ajax-powered load more button that loads additional blog posts to my wordpress site. I used the tutorial listed here: https://rudrastyh.com/wordpress/load-more-posts-ajax.html, and it works, but I've ran into another problem.
I have a session variable that counts the current post number. I show 10 posts per page and the counter works for the initial 10. Then I call the next 10 with ajax and instead of counting to 11, 12, 13 etc, it goes back to 1. There's clearly a problem with passing the end value (10) from the template, to the ajax handler in functions. Anyone know what could be wrong? Everything works if I don't use ajax - it's really frustrating.
Template PHP
<?php $_SESSION['the_counter'] = 0; ?>
<?php
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args = array(
'posts_per_page' => 10,
'paged' => $paged
);
$my_query = new WP_Query($args);
if($my_query->have_posts()): while($my_query->have_posts()) : $my_query->the_post();
get_template_part( 'template-parts/post/content', get_post_format() );
endwhile;
else:
get_template_part( 'no-results', 'home' );
endif;
if ( $my_query->max_num_pages > 1 ){
echo '</a><div class="misha_loadmore">More posts</div>';
}?>
</div>
<script>var posts_myajax = '<?php echo json_encode( $my_query->query_vars ) ?>',
current_page_myajax = 1,
max_page_myajax = <?php echo $my_query->max_num_pages ?>
</script>
<script src="/loadmore.js"></script>
<?php $my_query = null;
wp_reset_postdata();?>
Ajax Handler in functions.php
function misha_loadmore_ajax_handler(){
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // we need next page to be loaded
$args['post_status'] = 'publish';
query_posts( $args );
if( have_posts() ) :
// run the loop
while( have_posts() ): the_post();
// look into your theme code how the posts are inserted, but you can use your own HTML of course
// do you remember? - my example is adapted for Twenty Seventeen theme
get_template_part( 'template-parts/post/content', get_post_format() );
// for the test purposes comment the line above and uncomment the below one
// the_title();
endwhile;
endif;
die; }
add_action('wp_ajax_loadmore', 'misha_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmore', 'misha_loadmore_ajax_handler');
Load More JS
jQuery(function($){
$('.misha_loadmore').click(function(){
var button = $(this),
data = {
'action': 'loadmore',
'query': misha_loadmore_params.posts, // that's how we get params from wp_localize_script() function
'page' : misha_loadmore_params.current_page
};
$.ajax({
url : misha_loadmore_params.ajaxurl, // AJAX handler
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
button.text('Loading...'); // change the button text, you can also add a preloader image
},
success : function( data ){
if( data ) {
button.text( 'More posts' ).prev().before(data); // insert new posts
misha_loadmore_params.current_page++;
if ( misha_loadmore_params.current_page == misha_loadmore_params.max_page )
button.remove(); // if last page, remove the button
// you can also fire the "post-load" event here if you use a plugin that requires it
// $( document.body ).trigger( 'post-load' );
} else {
button.remove(); // if no data, remove the button as well
}
}
});
});});
And this is the session code I have on the top of my blog post content template file. It increments the count by 1 for every post.
$counter = $_SESSION['the_counter'];
$counter++;
$_SESSION['the_counter'] = $counter;
At the bottom of the file, I include:
echo insert_counter($the_counter);
At a glance, I'm betting sessions aren't being set. Try adding this to your functions.php file.
add_action('init', function() {
if (!session_id()) {
session_start();
});
This will ensure that sessions are loading on every page. It's worth mentioning that sessions aren't the best way to persist data. I would recommend replacing the session with a cookie.

Remove product in the cart using ajax in woocommerce

I would like to remove the product in the woocommerce cart using ajax without click the link.
If you have encounter this kind of functionality, please help us.
add_action( 'wp_footer', 'add_js_to_wp_wcommerce');
function add_js_to_wp_wcommerce(){ ?>
<script type="text/javascript">
jQuery('.remove-product').click(function(){
var product_id = jQuery(this).attr("data-product_id");
jQuery.ajax({
type: 'POST',
dataType: 'json',
url: "/wp-admin/admin-ajax.php",
data: { action: "product_remove",
product_id: product_id
},success: function(data){
console.log(data);
}
});
return false;
});
</script>
<?php }
add_action( 'wp_ajax_product_remove', 'product_remove' );
add_action( 'wp_ajax_nopriv_product_remove', 'product_remove' );
function product_remove() {
global $wpdb, $woocommerce;
session_start();
foreach ($woocommerce->cart->get_cart() as $cart_item_key => $cart_item){
if($cart_item['product_id'] == $_POST['product_id'] ){
// Remove product in the cart using cart_item_key.
$woocommerce->cart->get_remove_url($cart_item_key);
}
}
print_r($woocommerce->cart->get_cart());
//echo json_encode(array('status' => 0));
exit();
}
you could use the WC_Cart set_quantity method
And do as this in your php:
$cart = WC()->instance()->cart;
$id = $_POST['product_id'];
$cart_id = $cart->generate_cart_id($id);
$cart_item_id = $cart->find_product_in_cart($cart_id);
if($cart_item_id){
$cart->set_quantity($cart_item_id,0);
}
use this :
$cart = $woocommerce->cart;
foreach ($woocommerce->cart->get_cart() as $cart_item_key => $cart_item){
if($cart_item['product_id'] == $_POST['product_id'] ){
// Remove product in the cart using cart_item_key.
$cart->remove_cart_item($cart_item_key);
}
}
Try this one :
foreach ( $woocommerce->cart->cart_contents as $cart_item_key => $cart_item ) {
if($cart_item['product_id'] == $product_id){
unset($cartdetails->cart_contents[$cart_item_key]);
}
}

Resources