I recently worked on a WooCommerce custom site that only has 5 products. The design specified a single page website.

Realizing that I would not want the overhead to load all 5 products at once, I decided to retrieve each product via AJAX. The basic idea is that when the thumbnail for each product is clicked, the full product is loaded.

Here is a code snippet of the jQuery call to retrieve the product:

1
2
3
4
5
6
7
8
9
10
11
$.ajax({
  url: flatbikeurls.ajax_url,
  cache: false,
  type: "POST",
  headers : { "cache-control": "no-cache" },
  data: {
	'action': 'get_product_detail',
	'product_id': $productID
  },
  success:function(returned) {
      $( '#flatbike-product-detail__container' ).html(returned);

Of course we need to enqueue our script and make sure we have access to flatbikeurls.ajax_url:

1
2
3
4
5
6
7
function flatbike_scripts() {
	wp_enqueue_script( 'flatbike-js', get_template_directory_uri() . '/js/build/flatbike-production.min.js', array('jquery'), 'false', true );
	wp_localize_script( 'flatbike-js', 'flatbikeurls', array(
		'ajax_url' => admin_url( 'admin-ajax.php' )
	));
}
add_action( 'wp_enqueue_scripts', 'flatbike_scripts' );

You must also include the WordPress action to return the single product to the front end. Notice how we use the product ID that we passed along from our jQuery call. The call to “wc_get_template_part( ‘content’, ‘single-product’ );” returns the single product template with all the appropriate details.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function flatbike_get_product_detail() {
	$product_id = $_POST['product_id'];
	$args = array(
		'post_type' => 'product',
		'p'  => $product_id,
	);
	$query = new WP_Query( $args );
	if ($query->have_posts()) :
        while ($query->have_posts()) : $query->the_post();
            wc_get_template_part( 'content', 'single-product' );
        endwhile;
     else :
        echo "There were no posts found";
    endif;
    wp_reset_query();
	wp_die();
}
add_action('wp_ajax_get_product_detail', 'flatbike_get_product_detail');
add_action('wp_ajax_nopriv_get_product_detail', 'flatbike_get_product_detail');

The above was all working great until I need to add a variable product. While the options appeared nothing happened once an option was selected. The add to cart did not appear as expected.

It turns out there were 2 problems. The first was that the javascript that handles the variations form did not get loaded. The second, was that since the variation form was loaded via AJAX, the form was not available until the successful return from the AJAX call. So, to fix the issue, I added:

1
wp_enqueue_script( 'wc-add-to-cart-variation', plugins_url() . '/woocommerce/assets/js/frontend/add-to-cart-variation.min.js', array('jquery'), '2.4.8', true );

to the flatbike_scripts() function. I then made sure to call the javascript that handles the variations after a successful AJAX call. The code then looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$.ajax({
  url: flatbikeurls.ajax_url,
  cache: false,
  type: "POST",
  headers : { "cache-control": "no-cache" },
  data: {
	'action': 'get_product_detail',
	'product_id': $productID
  },
  success:function(returned) {
      $( '#flatbike-product-detail__container' ).html(returned);
      $form = $( '#flatbike-product-detail').find( '.variations_form' );
      if ($form) {
	$form.wc_variation_form();
      }