I am trying to add a file upload along with radio inputs in a custom woocommerce page; where all the products are showing in a list view.
The Custom Page CODE:
<?php /*
Template Name: Custom Woo Product List Page
*/ ?>
<?php get_header();?>
<div class="inn_page">
<table id="wh_table" class="table table-hover" width="100%" cellspacing="0">
<thead>
<tr>
<th></th>
<th>PRODUCT</th>
<th>Monogram letter or Message Box</th>
<th>PRICE</th>
<th>Product Total Quantity</th>
<th></th>
</tr>
</thead>
<tbody>
<?php
$args = array(
'post_type' => array('product', 'product_variation'),
'post_status' => array('publish'),
'posts_per_page' => -1,
'product_cat' => '',
'post__in' => array( 178, 39, 180, 101, 182, 108, 184, 171, 872, 877, 206, 197, 1028, 330, 216, 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;
?>
<?php if ( $product->is_type( 'variable' ) )
{
show_variable_products_list();
}
else
{
?>
<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" name="upload_form" id="upload_form" 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 letter_note(); ?>
<?php msg_note(); ?>
<?php upload_logo(); ?>
</td>
<td class="wh-price">
<span class="hiddenPrice"><?php echo $product->get_price_html() ?></span>
<span class="woocommerce-Price-amount ajaxPrice"><?php echo $product->get_price_html() ?></span>
</td>
</a>
<td class="quantity-field">
<?php woocommerce_quantity_input(); ?>
</td>
<td class="button-row">
<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 ); ?>" />
<div class="wh-button">
<button type="submit" class="single_add_to_cart_button btn btn-primary button wh-btn"><span class="glyphicon glyphicon-tag"></span> ADD TO CART</button>
</div>
</td>
</form>
</tr>
<?php } ?>
<?php endwhile; ?>
</tbody>
</table><!--/.products-->
<?php wp_reset_query(); ?>
</div>
<?php get_footer();?>
For variations to show in list view as different items/products in funtions.php
<?php
//----------------------------- START PRODUCT LIST VIEW PAGE CODE ----------------------------------
//-------------------------------------- Variations in Table List ---------------------------
function show_variable_products_list(){
global $product, $post;
$variations = find_valid_variations();
asort($variations);
foreach ($variations as $key => $value) {
if( !$value['variation_is_visible'] ) continue; ?>
<?php
$id_variation = $value['variation_id']
?>
<tr class="product-<?php echo esc_attr( $product->id ); ?> variation-<?php echo $value['variation_id']?> variations_form" data-role="product">
<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->id ); ?>" data-product_variations="<?php echo htmlspecialchars( json_encode( $available_variations ) ) ?>">
<td class="image">
<?php echo '<img src="'.$value['image_src'].'" alt="'.$product->get_title().'-'.$value['variation_id'].'" width="150px" height="150px" />'; ?>
</td>
<td class="title">
<h3><?php the_title(); ?></h3><br />
<b class="var-name"><?php
foreach($value['attributes'] as $attr_name => $attr_value ) {
$attr_name = 'pa_setting';
$attr = get_term_by('slug', $attr_value, $attr_name);
$attr_value = $attr->name;
echo $attr_value, ' ';
}
?></b>
<?php echo $id_variation ?>
</td>
<td class="note">
<?php letter_note(); ?>
<?php msg_note(); ?>
<?php upload_logo(); ?>
</td>
<td class="wh-price">
<span class="hiddenPrice"><?php echo $value['price_html'];?></span>
<span class="woocommerce-Price-amount ajaxPrice"><?php echo $value['price_html'];?></span>
</td>
<?php if( $value['is_in_stock'] ) { ?>
<td class="quantity-field">
<?php woocommerce_quantity_input(); ?>
</td>
<td class="button-row">
<?php
if(!empty($value['attributes'])){
foreach ($value['attributes'] as $attr_key => $attr_value) {
?>
<input type="hidden" name="<?php echo $attr_key?>" value="<?php echo $attr_value?>">
<?php
}
}
?>
<div class="wh-button">
<button type="submit" class="single_add_to_cart_button btn btn-primary button wh-btn"><span class="glyphicon glyphicon-tag"></span> ADD TO CART</button>
</div>
<input type="hidden" name="variation_id" class="variation_id" value="<?php echo $value['variation_id']?>" />
<input type="hidden" name="product_id" value="<?php echo esc_attr( $post->ID ); ?>" />
<input type="hidden" name="add-to-cart" value="<?php echo esc_attr( $post->ID ); ?>" />
<?php } else { ?>
<p class="stock out-of-stock"><?php _e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></p>
<?php } ?>
</td>
</form>
</tr>
<?php
}
}
?>
<?php
function find_valid_variations() {
global $product;
if ( $product->get_id() == 330 ) {
$variations = $product->get_available_variations();
//$attributes = $product->get_attributes();
$new_variants = array();
/* Show only the variations listed below */
foreach( $variations as $variation ) {
if ( $variation["variation_id"] == 971 || $variation["variation_id"] == 958 || $variation["variation_id"] == 945 || $variation["variation_id"] == 422 || $variation["variation_id"] == 412 || $variation["variation_id"] == 386 || $variation["variation_id"] == 358 ) {
$valid = true;
if( $valid )
$new_variants[] = $variation;
}
}
}
elseif ( $product->get_id() == 216 ) {
$variations = $product->get_available_variations();
$new_variants = array();
foreach( $variations as $variation ) {
if ( $variation["variation_id"] == 1010 || $variation["variation_id"] == 997 || $variation["variation_id"] == 984 || $variation["variation_id"] == 321 || $variation["variation_id"] == 295 || $variation["variation_id"] == 267 || $variation["variation_id"] == 237 ) {
$valid = true;
if( $valid )
$new_variants[] = $variation;
}
}
}
else {
$variations = $product->get_available_variations();
$attributes = $product->get_attributes();
$new_variants = array();
foreach( $variations as $variation ) {
$valid = true;
foreach( $attributes as $slug => $args ) {
if( array_key_exists("attribute_$slug", $variation['attributes']) && !empty($variation['attributes']["attribute_$slug"]) ) {
// Exists
} else {
$valid = false;
foreach( explode( '|', $attributes[$slug]['value']) as $attribute ) {
$attribute = trim( $attribute );
$new_variant = $variation;
$new_variant['attributes']["attribute_$slug"] = $attribute;
$new_variants[] = $new_variant;
}
}
}
if( $valid )
$new_variants[] = $variation;
}
}
return $new_variants;
}
add_filter( 'woocommerce_variable_add_to_cart', 'show_variable_products_list', 10, 2 );
?>
I am able to add the radio values to cart & order but not able to do anything with file upload.
Please take a look:
add_action("woocommerce_before_add_to_cart_button", "upload_logo", 9);
function upload_logo(){
?>
<div>
<p>Want to add Logo? <input type="checkbox" id="showHide" onclick="myFunction()"><b>Tick</b></p>
<p id="hiddenInputs" style="display:none">
<label for="radio_field">
Where you want the logo?
<input type="radio" name="radio_field" checked="checked" value="Front Side"> Front Side
<input type="radio" name="radio_field" value="Back Side"> Back Side
<input type="radio" name="radio_field" value="Both Side"> Both Side
</label> <br />
<label for="file_field">
Upload logo: <input type="file" name="file_field" value="">
</label> <br />
</p>
</div>
<script>
function myFunction() {
var checkboxToShowInputs = document.getElementById("showHide");
var showInputs = document.getElementById("hiddenInputs");
if (checkboxToShowInputs.checked == true){
showInputs.style.display = "block";
} else {
showInputs.style.display = "none";
}
}
</script>
<?php
}
/* Add File custom data to the cart item */
function file_upload_add_cart_item_data( $cart_item, $product_id ){
if( isset( $_POST['file_field'] ) ) {
$cart_item['logo_upload'] = $_POST['file_field'];
}
return $cart_item;
}
add_filter( 'woocommerce_add_cart_item_data', 'file_upload_add_cart_item_data', 10, 2 );
/* Add Radio custom data to the cart item */
// Stores the custom field value in Cart object
add_action( 'woocommerce_add_cart_item_data', 'save_custom_product_field_data', 10, 2 );
function save_custom_product_field_data( $cart_item, $product_id ) {
if( isset( $_REQUEST['radio_field'] ) ) {
$cart_item[ 'side_radio' ] = $_REQUEST['radio_field'];
// below statement make sure every add to cart action as unique line item
$cart_item['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'my_order_data', $_REQUEST['radio_field'] );
}
return $cart_item;
}
/* Load File cart data from session */
function file_upload_get_cart_item_from_session( $cart_item, $values ) {
if ( isset( $values['logo_upload'] ) ){
$cart_item['logo_upload'] = $values['logo_upload'];
}
return $cart_item;
}
add_filter( 'woocommerce_get_cart_item_from_session', 'file_upload_get_cart_item_from_session', 20, 2 );
/* Load Radio cart data from session */
function radio_get_cart_item_from_session( $cart_item, $values ) {
if ( isset( $values['side_radio'] ) ){
$cart_item['side_radio'] = $values['side_radio'];
}
return $cart_item;
}
add_filter( 'woocommerce_get_cart_item_from_session', 'radio_get_cart_item_from_session', 20, 2 );
/* Add File meta to order item */
function file_upload_add_order_item_meta( $item_id, $values ) {
if ( ! empty( $values['logo_upload'] ) ) {
woocommerce_add_order_item_meta( $item_id, 'logo_upload', $values['logo_upload'] );
}
}
add_action( 'woocommerce_add_order_item_meta', 'file_upload_add_order_item_meta', 10, 2 );
/* Add Radio meta to order item */
function radio_add_order_item_meta( $item_id, $values ) {
if ( ! empty( $values['side_radio'] ) ) {
woocommerce_add_order_item_meta( $item_id, 'side_radio', $values['side_radio'] );
}
}
add_action( 'woocommerce_add_order_item_meta', 'radio_add_order_item_meta', 10, 2 );
/* Get File item data to display in cart */
function file_upload_get_item_data( $other_data, $cart_item ) {
if ( ! empty ( $cart_item['logo_upload'] ) ){
$other_data[] = array(
'name' => __( 'Logo ', 'woocommerce' ),
'value' => $cart_item['logo_upload']
);
}
return $other_data;
}
add_filter( 'woocommerce_get_item_data', 'file_upload_get_item_data', 10, 2 );
/* Get Radio item data to display in cart */
function radio_get_item_data( $other_data, $cart_item ) {
if ( ! empty ( $cart_item['side_radio'] ) ){
$other_data[] = array(
'name' => __( 'Side ', 'woocommerce' ),
'value' => $cart_item['side_radio']
);
}
return $other_data;
}
add_filter( 'woocommerce_get_item_data', 'radio_get_item_data', 10, 2 );
/* Show File field in order overview */
function file_upload_order_item_product( $cart_item, $order_item ){
if( isset( $order_item['logo_upload'] ) ){
$cart_item_meta['logo_upload'] = $order_item['logo_upload'];
}
return $cart_item;
}
add_filter( 'woocommerce_order_item_product', 'file_upload_order_item_product', 10, 2 );
/* Show Radio field in order overview */
function radio_order_item_product( $cart_item, $order_item ){
if( isset( $order_item['side_radio'] ) ){
$cart_item_meta['side_radio'] = $order_item['side_radio'];
}
return $cart_item;
}
add_filter( 'woocommerce_order_item_product', 'radio_order_item_product', 10, 2 );
/* Add the File Upload field to order emails */
function file_upload_email_order_meta_fields( $fields ) {
$fields['custom_field'] = __( 'Logo ', 'woocommerce' );
return $fields;
}
add_filter('woocommerce_email_order_meta_fields', 'file_upload_email_order_meta_fields');
/* Add the Radio field to order emails */
function radio_email_order_meta_fields( $fields ) {
$fields['custom_field'] = __( 'Side ', 'woocommerce' );
return $fields;
}
add_filter('woocommerce_email_order_meta_fields', 'radio_email_order_meta_fields');
Here's the AJAX PHP
function ajax_add_to_cart_script() {
wp_enqueue_script( 'add-to-cart-wh_ajax', plugins_url() . '/wh-page-ajax-add-to-cart/js/add-to-cart-wh.js', array('jquery'), '', true );
}
add_action( 'wp_enqueue_scripts', 'ajax_add_to_cart_script',99 );
add_action( 'wp_ajax_woocommerce_add_to_cart_wh_sh', 'woocommerce_add_to_cart_wh_sh_callback' );
add_action( 'wp_ajax_nopriv_woocommerce_add_to_cart_wh_sh', 'woocommerce_add_to_cart_wh_sh_callback' );
function woocommerce_add_to_cart_wh_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'];
$letter = $_POST['_letter'];
$message = $_POST['_message'];
$radio = $_POST['radio_field'];
//$file = $_POST['file_field'];
$file = $_FILES['id_proof'];;
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $quantity, $cart_item_data, $letter, $message, $radio, $file );
if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $letter, $message, $radio, $file ) ) {
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();
}
And here's the edited js
/* AJAX Add to Cart Button */
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 .wh-btn', 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 letter = $variation_form.find('input[name=_wholesale_letter]').val();
var message = $variation_form.find('input[name=_wholesale_message]').val();
var rad = $variation_form.find('input[name=radio_field]:checked').val();
var file = $variation_form.find('input[name=file_field]').val();
//var file = $variation_form.find('input[name=file_field]').files[0].path;
//attributes = [];
$('.ajaxerrors').remove();
var item = {},
check = true;
variations = $variation_form.find('select[name^=attribute]');
/* Updated code to work with radio button - mantish - WC Variations Radio Buttons - 8manos */
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('has-error');
if (attributevalue.length === 0) {
index = attributeName.lastIndexOf('_');
attributeTaxName = attributeName.substring(index + 1);
$this
//.css( 'border', '1px solid red' )
.addClass('required has-error')
//.addClass( 'barizi-class' )
.before('<div class="ajaxerrors"><p>OH No Please select ' + attributeTaxName + '</p></div>')
//check = false;
} else {
item[attributeName] = attributevalue;
}
});
if (!check) {
return false;
}
/* Validate for All the input Message field */
var itemMessages = {},
checkmsg = true;
messages = $variation_form.find('input[name=_message');
messages.each(function() {
var $this = $(this),
attributeName = $this.attr('name'),
attributevalue = $this.val(),
index,
attributeTaxName;
$this.removeClass('required wh-error');
if (attributevalue.length === 0) {
index = attributeName.lastIndexOf('_');
attributeTaxName = attributeName.substring(index + 1);
$this
.removeClass('wh-input')
.addClass('required wh-error')
.before('<div class="ajaxerrors"><p><span style="font-weight: bold;">REQUIRED!</span> Please Type Some Text or Number.</p></div>')
//checkmsg = false;
} else {
itemMessages[attributeName] = attributevalue;
$this.addClass('wh-input');
}
});
if (!checkmsg) {
return false;
}
/* Validate One Letter Input Field */
var itemLetter = {},
checkltr = true;
letterOne = $variation_form.find('input[name=_letter]');
letterOne.each(function() {
var $this = $(this),
attributeName = $this.attr('name'),
attributevalue = $this.val(),
index,
attributeTaxName;
$this.removeClass('required wh-error');
if (attributevalue.length === 0) {
index = attributeName.lastIndexOf('_');
attributeTaxName = attributeName.substring(index + 1);
$this
/* .css({
'border': '2px solid #a94442',
'box-shadow': 'inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483'
})*/
.removeClass('wh-input')
.addClass('required wh-error')
.before('<div class="ajaxerrors"><p><span style="font-weight: bold;">REQUIRED!</span> Please Type 1 Letter or Number.</p></div>')
//checkmsg = false;
} else {
itemLetter[attributeName] = attributevalue;
$this.addClass('wh-input');
}
});
if (!checkltr) {
return false;
}
//item = JSON.stringify(item);
//alert(item);
//return false;
// AJAX add to cart request
var $thisbutton = $(this);
if ($thisbutton.is('.variations_form .wh-btn')) {
$thisbutton.removeClass('added');
$thisbutton.addClass('loading');
$thisbutton.attr("disabled", "disabled");
var data = {
action: 'woocommerce_add_to_cart_wh_sh',
product_id: product_id,
quantity: quantity,
variation_id: var_id,
variation: item,
_letter: letter,
_message: message,
radio_field: rad,
file_field: file
};
$.each($thisbutton.data(), function(key, value) {
data[key] = value;
});
// Trigger event
$('body').trigger('adding_to_cart', [$thisbutton, data]);
// Ajax action
$.post(wc_add_to_cart_params.ajax_url.toString().replace('%%endpoint%%', 'add_to_cart'), 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>' );
}
// View cart text
if (!wc_add_to_cart_params.is_cart && $variation_form.find('.added_to_cart').length === 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]);
}
})
.done(function(response) {
if ($variation_form.find('.added_to_cart').length === 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>');
}
$thisbutton.removeAttr("disabled", "disabled");
$thisbutton.removeClass('failed')
var quantity = $variation_form.find('input[name=quantity]').val("1");
var letter = $variation_form.find('input[name=_letter]').val("");
var message = $variation_form.find('input[name=_message]').val("");
var rad = $variation_form.find('input[name=radio_field]').val("Front Side");
})
.fail(function(response) {
setTimeout(function() {
$thisbutton.removeClass('loading');
$thisbutton.removeAttr("disabled", "disabled");
}, 2000);
$thisbutton.addClass('failed');
})
return false;
} else {
return true;
}
});
});
This page is only accessible to certain users, so it has different input fields, price than the single product page counterpart. Client don't like this page to be refreshed so I had to add AJAX, with the little knowledge I have. Now it's getting more complicated so please help me out.
Update 2019 - Corrected little mistake on radio buttons "name" attribute.
In your actual code, there is many mistakes as:
Here is your revisited code (much more lighter, compact and complete):
This code goes in function.php file of your active child theme (or active theme).
Frontend: orders display (and email notifications):
Backend (Admin): Display on orders edit pages: