I have created custom fields for specific products
//-------------------------- CUSTOM Front FIELD ----------------------
/*
* Display input on single product page
* @return html
*/
function message_front_note(){
global $product;
if ( $product->get_id() !== 451 ) {
return;
}
$value = isset( $_POST['_message_front'] ) ? sanitize_text_field( $_POST['_message_front'] ) : '';
printf( '<label>%s</label><input class="msg-note wh-input" name="_message_front" value="" maxlength="15" Placeholder="Up to 15 Letters or Numbers" />', __( 'Front', 'shf-custom-msg-front-fields' ), esc_attr( $value ) );
}
add_action( 'woocommerce_before_add_to_cart_button', 'message_front_note', 9 );
/*
* Validate when adding to cart
* @param bool $passed
* @param int $product_id
* @param int $quantity
* @return bool
*/
function shf_add_to_cart_validation($passed, $product_id, $qty){
if ( isset( $_POST['_message_front'] ) && sanitize_text_field( $_POST['_message_front'] ) == '' ) {
$product = wc_get_product( $product_id );
wc_add_notice( sprintf( __( '%s cannot be added to the cart until you enter some text.', 'shf-custom-msg-front-fields' ), $product->get_title() ), 'error' );
return false;
}
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'shf_add_to_cart_validation', 10, 3 );
/*
* Add custom data to the cart item
* @param array $cart_item
* @param int $product_id
* @return array
*/
function shf_add_cart_item_data( $cart_item, $product_id ){
if( isset( $_POST['_message_front'] ) ) {
$cart_item['message_front'] = sanitize_text_field( $_POST['_message_front'] );
}
return $cart_item;
}
add_filter( 'woocommerce_add_cart_item_data', 'shf_add_cart_item_data', 10, 2 );
/*
* Load cart data from session
* @param array $cart_item
* @param array $other_data
* @return array
*/
function shf_get_cart_item_from_session( $cart_item, $values ) {
if ( isset( $values['message_front'] ) ){
$cart_item['message_front'] = $values['message_front'];
}
return $cart_item;
}
add_filter( 'woocommerce_get_cart_item_from_session', 'shf_get_cart_item_from_session', 20, 2 );
/*
* Add meta to order item
* @param int $item_id
* @param array $values
* @return void
*/
function shf_add_order_item_meta( $item_id, $values ) {
if ( ! empty( $values['message_front'] ) ) {
woocommerce_add_order_item_meta( $item_id, 'message_front', $values['message_front'] );
}
}
add_action( 'woocommerce_add_order_item_meta', 'shf_add_order_item_meta', 10, 2 );
/*
* Get item data to display in cart
* @param array $other_data
* @param array $cart_item
* @return array
*/
function shf_get_item_data( $other_data, $cart_item ) {
if ( isset( $cart_item['message_front'] ) ){
$other_data[] = array(
'name' => __( 'Front ', 'shf-custom-msg-front-fields' ),
'value' => sanitize_text_field( $cart_item['message_front'] )
);
}
return $other_data;
}
add_filter( 'woocommerce_get_item_data', 'shf_get_item_data', 10, 2 );
/*
* Show custom field in order overview
* @param array $cart_item
* @param array $order_item
* @return array
*/
function shf_order_item_product( $cart_item, $order_item ){
if( isset( $order_item['message_front'] ) ){
$cart_item_meta['message_front'] = $order_item['message_front'];
}
return $cart_item;
}
add_filter( 'woocommerce_order_item_product', 'shf_order_item_product', 10, 2 );
/*
* Add the field to order emails
* @param array $keys
* @return array
*/
function shf_email_order_meta_fields( $fields ) {
$fields['custom_field'] = __( 'Front ', 'shf-custom-msg-front-fields' );
return $fields;
}
add_filter('woocommerce_email_order_meta_fields', 'shf_email_order_meta_fields');
I am showing products in table rows. Everything works just fine, the custom fields get posted to cart or show error wc_print_notices();
if not filled up. The problem occurs when I try to use AJAX submission with it. AJAX submits the product, quantity and even variations but it doesn't post the custom field and if I use AJAX then it'll not show error if the field is not filled up, it bypasses the validation and submits the product anyway.
I am out of league here.
Product HTML
<div class="inn_page">
<table id="wh_table" class="table table-hover" width="100%" cellspacing="0">
<thead>
<tr>
<th></th>
<th>PRODUCT</th>
<th>Message Box</th>
<th>PRICE</th>
<th>Quantity</th>
<th></th>
</tr>
</thead>
<tbody>
<?php
$args = array(
'post_type' => array('product', 'product_variation'),
'post_status' => array('publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit'),
'posts_per_page' => -1,
'product_cat' => '',
'post__in' => array( 451, 481, 478, 589 ),
'orderby' => 'post__in',
//'order' => 'DESC',
'paged' => get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1 );
$wp_query = new WP_Query( $args );
while ( $wp_query->have_posts() ) : $wp_query->the_post();
global $product;
?>
<tr class="product-<?php echo esc_attr( $product->id ); ?> variations_form" data-role="product">
<form action="<?php echo esc_url( $product->add_to_cart_url() ); ?>" class="cart" method="post" enctype='multipart/form-data'>
<a href="<?php echo get_permalink( $wp_query->post->ID ) ?>" title="<?php echo esc_attr($wp_query->post->post_title ? $wp_query->post->post_title : $wp_query->post->ID); ?>">
<td class="image">
<?php woocommerce_show_product_sale_flash( $post, $product ); ?>
<?php if (has_post_thumbnail( $wp_query->post->ID )) echo get_the_post_thumbnail($wp_query->post->ID, 'wh_catalog'); else echo '<img src="'.woocommerce_placeholder_img_src().'" alt="Placeholder" width="150px" height="150px" />'; ?>
</td>
<td class="title">
<h3><?php the_title(); ?></h3>
<?php if ( ($product->get_id() == 178) || ($product->get_id() == 589) ) { ?>
<b>Sterling Silver</b>
<?php } ?>
</td>
<td class="note">
<?php wholesale_message_front_note(); ?>
</td>
<td class="wh-price">
<span><?php echo $product->get_price_html() ?></span>
</td>
</a>
<td class="quantity-field">
<?php woocommerce_quantity_input(); ?>
</td>
<td class="button">
<input type="hidden" name="add-to-cart" value="<?php echo esc_attr( $product->id ); ?>" />
<input type="hidden" name="product_id" value="<?php echo esc_attr( $product->id ); ?>" id="product_id" />
<input value="1" id="product_quantity" type="hidden">
<button type="submit" class="single_add_to_cart_button btn btn-primary button alt ajax_add_to_cart add_to_cart_button product_type_simple"><span class="glyphicon glyphicon-tag"></span> ADD TO CART</button>
</td>
</form>
</tr>
<?php endwhile; ?>
</tbody>
</table>
<!--/.products-->
<?php wp_reset_query(); ?>
</div>
PHP for the AJAX
function ajax_add_to_cart_script() {
wp_enqueue_script( 'add-to-cart_ajax', get_template_directory_uri().'/js/add_to_cart_test.js', array('jquery'), '', true );
}
add_action( 'wp_enqueue_scripts', 'ajax_add_to_cart_script',99 );
add_action( 'wp_ajax_woocommerce_add_to_cart_sh', 'woocommerce_add_to_cart_wholesale_sh_callback' );
add_action( 'wp_ajax_nopriv_woocommerce_add_to_cart_sh', 'woocommerce_add_to_cart_sh_callback' );
function woocommerce_add_to_cart_sh_callback() {
ob_start();
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_POST['product_id'] ) );
$quantity = empty( $_POST['quantity'] ) ? 1 : apply_filters( 'woocommerce_stock_amount', $_POST['quantity'] );
$variation_id = $_POST['variation_id'];
$variation = $_POST['variation'];
$message_front = $_POST['_message_front'];
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $message_front );
if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $message_front ) ) {
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 );
}
// Return fragments
WC_AJAX::get_refreshed_fragments();
} else {
$this->json_headers();
// If there was an error adding to the cart, redirect to the product page to show any errors
$data = array(
'error' => true,
'product_url' => apply_filters( 'woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id )
);
echo json_encode( $data );
}
die();
}
JS for the AJAX
jQuery( function( $ ) {
// wc_add_to_cart_params is required to continue, ensure the object exists
if ( typeof wc_add_to_cart_params === 'undefined' )
return false;
// Ajax add to cart
$( document ).on( 'click', '.variations_form .single_add_to_cart_button', function(e) {
e.preventDefault();
$variation_form = $( this ).closest( '.variations_form' );
var var_id = $variation_form.find( 'input[name=variation_id]' ).val();
var product_id = $variation_form.find( 'input[name=product_id]' ).val();
var quantity = $variation_form.find( 'input[name=quantity]' ).val();
var message_front = $variation_form.find( 'input[name=_message_front]' ).val();
//attributes = [];
$( '.ajaxerrors' ).remove();
var item = {},
check = true;
variations = $variation_form.find( 'select[name^=attribute]' );
if ( !variations.length) {
variations = $variation_form.find( '[name^=attribute]:checked' );
}
/* Backup Code for getting input variable */
if ( !variations.length) {
variations = $variation_form.find( 'input[name^=attribute]' );
}
variations.each( function() {
var $this = $( this ),
attributeName = $this.attr( 'name' ),
attributevalue = $this.val(),
index,
attributeTaxName;
$this.removeClass( 'error' );
if ( attributevalue.length === 0 ) {
index = attributeName.lastIndexOf( '_' );
attributeTaxName = attributeName.substring( index + 1 );
$this
//.css( 'border', '1px solid red' )
.addClass( 'required error' )
//.addClass( 'barizi-class' )
.before( '<div class="ajaxerrors"><p>Please select ' + attributeTaxName + '</p></div>' )
check = false;
} else {
item[attributeName] = attributevalue;
}
// Easy to add some specific code for select but doesn't seem to be needed
// if ( $this.is( 'select' ) ) {
// } else {
// }
} );
if ( !check ) {
return false;
}
//item = JSON.stringify(item);
//alert(item);
//return false;
// AJAX add to cart request
var $thisbutton = $( this );
if ( $thisbutton.is( '.variations_form .single_add_to_cart_button' ) ) {
$thisbutton.removeClass( 'added' );
$thisbutton.addClass( 'loading' );
var data = {
action: 'woocommerce_add_to_cart_sh',
product_id: product_id,
quantity: quantity,
variation_id: var_id,
variation: item,
message_front: message_front
};
// Trigger event
$( 'body' ).trigger( 'adding_to_cart', [ $thisbutton, data ] );
// Ajax action
$.post( wc_add_to_cart_params.ajax_url, data, function( response ) {
if ( ! response )
return;
var this_page = window.location.toString();
this_page = this_page.replace( 'add-to-cart', 'added-to-cart' );
if ( response.error && response.product_url ) {
window.location = response.product_url;
return;
}
if ( wc_add_to_cart_params.cart_redirect_after_add === 'yes' ) {
window.location = wc_add_to_cart_params.cart_url;
return;
} else {
$thisbutton.removeClass( 'loading' );
var fragments = response.fragments;
var cart_hash = response.cart_hash;
// Block fragments class
if ( fragments ) {
$.each( fragments, function( key ) {
$( key ).addClass( 'updating' );
});
}
// Block widgets and fragments
$( '.shop_table.cart, .updating, .cart_totals' ).fadeTo( '400', '0.6' ).block({
message: null,
overlayCSS: {
opacity: 0.6
}
});
// Changes button classes
$thisbutton.addClass( 'added' );
// View cart text
if ( ! wc_add_to_cart_params.is_cart && $thisbutton.parent().find( '.added_to_cart' ).size() === 0 ) {
$thisbutton.after( ' <a href="' + wc_add_to_cart_params.cart_url + '" class="added_to_cart wc-forward" title="' +
wc_add_to_cart_params.i18n_view_cart + '">' + wc_add_to_cart_params.i18n_view_cart + '</a>' );
}
// Replace fragments
if ( fragments ) {
$.each( fragments, function( key, value ) {
$( key ).replaceWith( value );
});
}
// Unblock
$( '.widget_shopping_cart, .updating' ).stop( true ).css( 'opacity', '1' ).unblock();
// Cart page elements
$( '.shop_table.cart' ).load( this_page + ' .shop_table.cart:eq(0) > *', function() {
$( '.shop_table.cart' ).stop( true ).css( 'opacity', '1' ).unblock();
$( document.body ).trigger( 'cart_page_refreshed' );
});
$( '.cart_totals' ).load( this_page + ' .cart_totals:eq(0) > *', function() {
$( '.cart_totals' ).stop( true ).css( 'opacity', '1' ).unblock();
});
// Trigger event so themes can refresh other areas
$( document.body ).trigger( 'added_to_cart', [ fragments, cart_hash, $thisbutton ] );
}
});
console.log (error);
return false;
} else {
return true;
}
});
});
$message_front = $_POST['_message_front'];
doesn't have anything stored. What am I doing wrong? I am bit lost here, please help me out.
A simple underscore made my nights sleepless for the past few days.
message_front
should be_message_front