I have a code that shows the checkbox on the product edit page. When I click on this checkbox, a select box is displayed on the single product page.
Here is my code:
// Display Checkbox Field
add_action('woocommerce_product_options_general_product_data', 'roast_custom_field_add');
function roast_custom_field_add(){
global $post;
// Checkbox
woocommerce_wp_checkbox(
array(
'id' => '_roast_checkbox',
'label' => __('Roast Level', 'woocommerce' ),
'description' => __( 'Enable roast level!', 'woocommerce' )
)
);
}
// Save Checkbox Field
add_action('woocommerce_process_product_meta', 'roast_custom_field_save');
function roast_custom_field_save($post_id){
// Custom Product Checkbox Field
$roast_checkbox = isset( $_POST['_roast_checkbox'] ) ? 'yes' : 'no';
update_post_meta($post_id, '_roast_checkbox', esc_attr( $roast_checkbox ));
}
// Display Select Box
add_action( 'woocommerce_before_add_to_cart_button', 'add_roast_custom_field', 0 );
function add_roast_custom_field() {
global $post;
// If is single product page and have the "roast_checkbox" enabled we display the field
if ( is_product() && get_post_meta( $post->ID, '_roast_checkbox', true ) == 'yes' ) {
echo '<div>';
woocommerce_form_field( 'roast_custom_options', array(
'type' => 'select',
'class' => array('my-field-class form-row-wide'),
'label' => __('Roast Level'),
'required' => false,
'options' => array(
'' => 'Please select',
'Blue' => 'Blue',
'Rare' => 'Rare',
'Medium Rare' => 'Medium Rare',
'Medium' => 'Medium',
'Medium Well' => 'Medium Well',
'Well Done' => 'Well Done'
)
), '' );
echo '</div>';
}
}
When you click on the checkbox, the selection field is shown correctly.
But the data, after selecting the options are not saved.
Also, these data are not displayed on the cart page, on the checkout page, in the order, etc.
Нere is my code:
// Save roast custom field
add_action( 'woocommerce_add_to_cart', 'roast_custom_field_add_to_cart', 20, 6 );
function roast_custom_field_add_to_cart( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ){
if( isset($_POST['roast_custom_options']) ){
$roast_values = (array) get_post_meta( $product_id, '_roast_custom_options_values', true );
$roast_values[] = sanitize_text_field( $_POST['roast_custom_options'] );
update_post_meta( $product_id, '_roast_custom_options_values', $roast_values );
}
}
// Add custom fields values under cart item name in cart
add_filter( 'woocommerce_cart_item_name', 'roast_custom_field', 10, 3 );
function roast_custom_field( $item_name, $cart_item, $cart_item_key ) {
if( ! is_cart() )
return $item_name;
if( $roast_values = $cart_item['data']->get_meta('_roast_custom_options_values') ) {
$item_name .= '<br /><div class="my-custom-class"><strong>' . __("Roast Level", "woocommerce") . ':</strong> ' . $roast_values . ' </div>';
}
return $item_name;
}
// Display roast custom fields values under item name in checkout
add_filter( 'woocommerce_checkout_cart_item_quantity', 'roast_custom_checkout_cart_item_name', 10, 3 );
function roast_custom_checkout_cart_item_name( $item_qty, $cart_item, $cart_item_key ) {
if( $roast_values = $cart_item['data']->get_meta('_roast_custom_options_values') ) {
$item_qty .= '<br /><div class="my-custom-class"><strong>' . __("Roast Level", "woocommerce") . ':</strong> ' . $roast_values . ' </div>';
}
return $item_qty;
}
// Display roast custom fields values on orders and email notifications
add_filter( 'woocommerce_order_item_name', 'roast_custom_order_item_name', 10, 2 );
function roast_custom_order_item_name( $item_name, $item ) {
$product = $item->get_product();
if( $roast_values = $product->get_meta('_roast_custom_options_values') ) {
$item_name .= '<br /><span class="my-custom-class"><strong>' . __("Roast Level", "woocommerce") . ':</strong> ' . $roast_values . ' </span>';
}
return $item_name;
}
How to fix the code so that everything works correctly?
I have revisited your code "in a hurry", also added some missing function and removed another one:
// Display Checkbox Field
add_action('woocommerce_product_options_general_product_data', 'roast_custom_field_add');
function roast_custom_field_add(){
global $post;
// Checkbox
woocommerce_wp_checkbox(
array(
'id' => '_roast_checkbox',
'label' => __('Roast Level', 'woocommerce' ),
'description' => __( 'Enable roast level!', 'woocommerce' )
)
);
}
// Save Checkbox Field
add_action('woocommerce_process_product_meta', 'roast_custom_field_save');
function roast_custom_field_save($post_id){
// Custom Product Checkbox Field
$roast_checkbox = isset( $_POST['_roast_checkbox'] ) ? 'yes' : 'no';
update_post_meta($post_id, '_roast_checkbox', esc_attr( $roast_checkbox ));
}
// Display Select Box
add_action( 'woocommerce_before_add_to_cart_button', 'add_roast_custom_field', 0 );
function add_roast_custom_field() {
global $product;
// If is single product page and have the "roast_checkbox" enabled we display the field
if ( is_product() && $product->get_meta( '_roast_checkbox' ) === 'yes' ) {
echo '<div>';
woocommerce_form_field( 'roast_custom_options', array(
'type' => 'select',
'class' => array('my-field-class form-row-wide'),
'label' => __('Roast Level'),
'required' => false,
'options' => array(
'' => 'Please select',
'Blue' => 'Blue',
'Rare' => 'Rare',
'Medium Rare' => 'Medium Rare',
'Medium' => 'Medium',
'Medium Well' => 'Medium Well',
'Well Done' => 'Well Done'
)
), '' );
echo '</div>';
}
}
// Add as custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'add_custom_cart_item_data', 10, 3 );
function add_custom_cart_item_data($cart_item_data, $product_id, $variation_id ){
if( isset( $_POST['roast_custom_options'] ) ) {
$cart_item_data['roast_option'] = wc_clean( $_POST['roast_custom_options'] );
}
return $cart_item_data;
}
// Add custom fields values under cart item name in cart
add_filter( 'woocommerce_cart_item_name', 'roast_custom_field', 10, 3 );
function roast_custom_field( $item_name, $cart_item, $cart_item_key ) {
if( ! is_cart() )
return $item_name;
if( isset($cart_item['roast_option']) ) {
$item_name .= '<br /><div class="my-custom-class"><strong>' . __("Roast Level", "woocommerce") . ':</strong> ' . $cart_item['roast_option'] . '</div>';
}
return $item_name;
}
// Display roast custom fields values under item name in checkout
add_filter( 'woocommerce_checkout_cart_item_quantity', 'roast_custom_checkout_cart_item_name', 10, 3 );
function roast_custom_checkout_cart_item_name( $item_qty, $cart_item, $cart_item_key ) {
if( isset($cart_item['roast_option']) ) {
$item_qty .= '<br /><div class="my-custom-class"><strong>' . __("Roast Level", "woocommerce") . ':</strong> ' . $cart_item['roast_option'] . 'гр.</div>';
}
return $item_qty;
}
// Save chosen slelect field value to each order item as custom meta data and display it everywhere
add_action('woocommerce_checkout_create_order_line_item', 'save_order_item_product_fitting_color', 10, 4 );
function save_order_item_product_fitting_color( $item, $cart_item_key, $values, $order ) {
if( isset($values['roast_option']) ) {
$key = __('Roast Level', 'woocommerce');
$value = $values['roast_option'];
$item->update_meta_data( $key, $value );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
On frontend Cart page:
On backend Order edit pages:
On email notifications:
Your checkbox value is stored to database, try to change this code
$roast_checkbox = isset( $_POST['_roast_checkbox'] ) ? 'yes' : 'no';
with
if ( isset( $_POST['_roast_checkbox'] ) {
$roast_checkbox = $_POST['_roast_checkbox'];
//update_post_meta
}
Related
I've added a Custom SKU in products to use for vendor SKU for order confirmation email. What I've created works only for simple products and not variable products.
Custom SKU,
I added this to the functions.php
function jk_add_custom_sku() {
$args = array(
'label' => __( 'Custom SKU', 'woocommerce' ),
'placeholder' => __( 'Enter custom SKU here', 'woocommerce' ),
'id' => 'jk_sku',
'desc_tip' => true,
'description' => __( 'This SKU is for internal use only.', 'woocommerce' ),
);
woocommerce_wp_text_input( $args );
}
add_action( 'woocommerce_product_options_sku', 'jk_add_custom_sku' );
function jk_save_custom_sku( $post_id ) {
// grab the custom SKU from $_POST
$custom_sku = isset( $_POST[ 'jk_sku' ] ) ? sanitize_text_field( $_POST[ 'jk_sku' ] ) : '';
// grab the product
$product = wc_get_product( $post_id );
// save the custom SKU using WooCommerce built-in functions
$product->update_meta_data( 'jk_sku', $custom_sku );
$product->save();
}
add_action( 'woocommerce_process_product_meta', 'jk_save_custom_sku' );
Next I modified the email template email-order-items.php adding to the SKU section to check if Custom SKU exists.
<?php
// Show title/image etc.
if ( $show_image ) {
echo wp_kses_post( apply_filters( 'woocommerce_order_item_thumbnail', $image, $item ) );
}
// Product name.
echo wp_kses_post( apply_filters( 'woocommerce_order_item_name', $item->get_name(), $item, false ) );
// SKU.
if ( $show_sku && $sku ) {
echo wp_kses_post( ' (#' . $sku . ')' );
// load the custom SKU
$custom_sku = get_post_meta( $product->get_id(), 'jk_sku', true );
if ( is_string( $custom_sku ) ) { // only show the custom SKU if it's set
echo "<br>" . wp_kses_post( "Custom SKU: $custom_sku" ); // change this line if needed
}
}
// allow other plugins to add additional product information here.
do_action( 'woocommerce_order_item_meta_start', $item_id, $item, $order, $plain_text );
wc_display_item_meta(
$item,
array(
'label_before' => '<strong class="wc-item-meta-label" style="float: ' . esc_attr( $text_align ) . '; margin-' . esc_attr( $margin_side ) . ': .25em; clear: both">',
)
);
// allow other plugins to add additional product information here.
do_action( 'woocommerce_order_item_meta_end', $item_id, $item, $order, $plain_text );
?>
</td>
The Custom SKU only shows up on the email for Simple products. I need it to work with Variable products. There is only one Custom SKU for each product not for each variable product.
I have revisited a bit your code and changed the meta key to _sku2 just like WooCommerce meta keys starting with an underscore:
add_action( 'woocommerce_product_options_sku', 'add_product_sku2_custom_field' );
function add_product_sku2_custom_field() {
$field_key = '_sku2';
woocommerce_wp_text_input( array(
'id' => $field_key,
'label' => __( 'Custom SKU', 'woocommerce' ),
'placeholder' => __( 'Enter custom SKU here', 'woocommerce' ),
'desc_tip' => true,
'description' => __( 'This SKU is for internal use only.', 'woocommerce' ),
) );
}
add_action( 'woocommerce_admin_process_product_object', 'save_product_sku2_custom_field_value' );
function save_product_sku2_custom_field_value( $product ) {
$field_key = '_sku2';
if ( isset($_POST[$field_key]) ) {
$product->update_meta_data( $field_key, sanitize_text_field($_POST[$field_key]) );
}
}
For product variations, you need to get the parent variable product to get a "Custom sku" displayed (see at the code at the end)
Now to enable an additional custom SKU to product variations of a variable product too, use the following:
add_action( 'woocommerce_variation_options_pricing', 'add_product_variation_sku2_custom_field', 10, 3 );
function add_product_variation_sku2_custom_field( $loop, $variation_data, $variation ){
$field_key = '_sku2';
woocommerce_wp_text_input( array(
'id' => $field_key.'['.$loop.']',
'label' => __( 'Custom SKU', 'woocommerce' ),
'placeholder' => __( 'Enter custom SKU here', 'woocommerce' ),
'desc_tip' => true,
'description' => __( 'This SKU is for internal use only.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, $field_key, true )
) );
}
add_action( 'woocommerce_save_product_variation', 'save_product_variation_sku2_custom_field_value', 10, 2 );
function save_product_variation_sku2_custom_field_value( $variation_id, $i ){
$field_key = '_sku2';
if( isset($_POST[$field_key][$i]) ){
update_post_meta( $variation_id, $field_key, sanitize_text_field($_POST[$field_key][$i]) );
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
And in your template custom code you will replace:
// SKU.
if ( $show_sku && $sku ) {
echo wp_kses_post( ' (#' . $sku . ')' );
// load the custom SKU
$custom_sku = get_post_meta( $product->get_id(), 'jk_sku', true );
if ( is_string( $custom_sku ) ) { // only show the custom SKU if it's set
echo "<br>" . wp_kses_post( "Custom SKU: $custom_sku" ); // change this line if needed
}
}
by the following (that will work for variable products or product variations):
// SKU (and SKU2)
if ( $show_sku && $sku ) {
echo wp_kses_post( ' (#' . $sku . ')' );
// load the custom SKU
$sku2 = $product->get_meta('_sku2');
// For product variations with empty SKU (get the parent variable product SKU)
if ( empty($sku2) && $product->is_type('variation') ) {
// Get parent variable product Id
$parent_product_id = $product->get_parent_id();
$parent_product = wc_get_product($parent_product_id);
$sku2 = $parent_product->get_meta('_sku2');
}
// only show the custom SKU if it's set (and product variation too)
if ( ! empty($sku2) ) {
echo "<br>" . wp_kses_post( sprintf( __("Custom SKU: %s", "woocommerce"), $sku2 ) ); // change this line if needed
}
}
For product variations, if there is not any "custom sku", it will try to get the parent variable product "custom sku".
It should work.
I have a variable Table, that I need to show stock levels per location - and not the total stock for each product - as it currently is.
The plugin used: Woocommerce Variations to Table - Grid
Added the fields in the variation by the functions.php method
below is the code that the Variations Table Grid use to show the stock number.
<?php
if ($vartable_stock == 1) {
if (absint($vartable_low_stock_thresh) > 0 && $varstock < absint($vartable_low_stock_thresh) && get_post_meta($value['variation_id'], '_manage_stock', true) == 'yes' ) {
$allcolumns['vartable_stock'] = '<td class="stockcol" data-label="'. apply_filters('vartable_dl_stock', $headenames['vartable_stock'], $value) .'">'. (get_post_meta($value['variation_id'], '_stock_status', true) != 'outofstock' && $varstock > 0 ? '<span class="lowstock">'. str_replace ('%n', $varstock, __($vartable_low_stock_text, 'vartable')) .'</span>' : '<span class="outofstock">'.__($vartable_out_stock_text, 'vartable').'</span>') .'</td>';
} else {
$allcolumns['vartable_stock'] = '<td class="stockcol" data-label="'. apply_filters('vartable_dl_stock', $headenames['vartable_stock'], $value) .'">'. (get_post_meta($value['variation_id'], '_stock_status', true) != 'outofstock' ? '<span class="instock">'. str_replace ('%n', $varstock, __($vartable_in_stock_text, 'vartable')) .'</span>' : '<span class="outofstock">'.__($vartable_out_stock_text, 'vartable').'</span>') .'</td>';
}
}
?>
This shows the Stock Levels for each variation as seen in the image below.
Here is what it looks like in the backend of the product:
Here is the code that I used for adding those four custom fields into the product variation.
// 1. Add custom field input # Product Data > Variations > Single Variation
add_action( 'woocommerce_variation_options_pricing', 'stock_warehouse_add_custom_field_to_variations', 10, 3 );
// Durban Stock Number
function stock_warehouse_add_custom_field_to_variations( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input( array(
'id' => 'stock_level_durban[' . $loop . ']',
'class' => 'short',
'label' => __( 'Durban Stock', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, 'stock_level_durban', true )
)
);
// Cape Town Stock Number
woocommerce_wp_text_input( array(
'id' => 'stock_level_cape_town[' . $loop . ']',
'class' => 'short',
'label' => __( 'Cape Town Stock', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, 'stock_level_cape_town', true )
)
);
// PE Stock Number
woocommerce_wp_text_input( array(
'id' => 'stock_level_pe[' . $loop . ']',
'class' => 'short',
'label' => __( 'Port Elizabeth Stock', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, 'stock_level_pe', true )
)
);
// JHB Stock Number
woocommerce_wp_text_input( array(
'id' => 'stock_level_jhb[' . $loop . ']',
'class' => 'short',
'label' => __( 'JHB Stock', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, 'stock_level_jhb', true )
)
);
}
// -----------------------------------------
// 2. Save custom field on product variation save
add_action( 'woocommerce_save_product_variation', 'stock_warehouse_save_custom_field_to_variations', 10, 2 );
function stock_warehouse_save_custom_field_to_variations( $variation_id, $i ) {
$stock_level_durban = $_POST['stock_level_durban'][$i];
if ( isset( $stock_level_durban ) ) update_post_meta( $variation_id, 'stock_level_durban', esc_attr( $stock_level_durban ) );
$stock_level_cape_town = $_POST['stock_level_cape_town'][$i];
if ( isset( $stock_level_cape_town ) ) update_post_meta( $variation_id, 'stock_level_cape_town', esc_attr( $stock_level_cape_town ) );
$stock_level_pe = $_POST['stock_level_pe'][$i];
if ( isset( $stock_level_pe ) ) update_post_meta( $variation_id, 'stock_level_pe', esc_attr( $stock_level_pe ) );
$stock_level_jhb = $_POST['stock_level_jhb'][$i];
if ( isset( $stock_level_jhb) ) update_post_meta( $variation_id, 'stock_level_jhb', esc_attr( $stock_level_jhb) );
}
// -----------------------------------------
// 3. Store custom field value into variation data
add_filter( 'woocommerce_available_variation', 'stock_warehouse_add_custom_field_variation_data' );
function stock_warehouse_add_custom_field_variation_data( $variations ) {
$variations['stock_level_durban'] = '<div class="woocommerce_custom_field">Durban Stock: <span>' . get_post_meta( $variations[ 'variation_id' ], 'stock_level_durban', true ) . '</span></div>';
$variations['stock_level_cape_town'] = '<div class="woocommerce_custom_field">Cape Town Stock: <span>' . get_post_meta( $variations[ 'variation_id' ], 'stock_level_cape_town', true ) . '</span></div>';
$variations['stock_level_pe'] = '<div class="woocommerce_custom_field">PE Stock: <span>' . get_post_meta( $variations[ 'variation_id' ], 'stock_level_pe', true ) . '</span></div>';
$variations['stock_level_jhb'] = '<div class="woocommerce_custom_field">JHB Stock: <span>' . get_post_meta( $variations[ 'variation_id' ], 'stock_level_jhb', true ) . '</span></div>';
return $variations;
}
function woo_hide_product_categories_widget( $list_args ){
$list_args[ 'hide_empty' ] = 1;
return $list_args;
}
add_filter( 'woocommerce_product_categories_widget_args', 'woo_hide_product_categories_widget' );
add_filter( 'get_terms', 'get_subcategory_terms', 10, 3 );
function get_subcategory_terms( $terms, $taxonomies, $args ) {
$new_terms = array();
// if a product category and on the shop page
if ( in_array( 'product_cat', $taxonomies ) && ! is_admin() ) {
foreach ( $terms as $key => $term ) {
if ( ! in_array( $term->slug, array( 'uncategorized' ) ) ) {
$new_terms[] = $term;
}
}
$terms = $new_terms;
}
return $terms;
}
add_filter( 'woocommerce_product_add_to_cart_text', function( $text ) {
global $product;
if ( $product->is_type( 'variable' ) ) {
$text = $product->is_purchasable() ? __( 'View', 'woocommerce' ) : __( 'View', 'woocommerce' );
}
return $text;
}, 10 );
add_filter( 'woocommerce_attribute_label', 'rename_color_attribute_label', 10, 3);
function rename_color_attribute_label($label, $name, $product){
if(strtolower($label)=='colour'){
$label = 'Variant';
}
return $label;
}
I am trying to get the SOH to show like 0/0/0/28 instead of just the total "28" so that customers can see where the stock is located and not just the total amount.
I have add a custom field for each product variation of my store :
add_action( 'woocommerce_variation_options_pricing', 'bbloomer_add_rangement_to_variations', 10, 3 );
function bbloomer_add_rangement_to_variations( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input( array(
'id' => 'rangement[' . $loop . ']',
'placeholder' => 'Ex : Armoire 2',
'label' => __('Rangement', 'woocommerce'),
'desc_tip' => 'true',
'class' => 'short',
'wrapper_class' => 'form-row',
'value' => get_post_meta( $variation->ID, 'rangement', true )
)
);
}
And I have stored this into variation metadata
// 3. Store custom field value into variation data
add_filter( 'woocommerce_available_variation', 'bbloomer_add_rangement_variation_data' );
function bbloomer_add_rangement_variation_data( $variations ) {
$variations['rangement'] = '<div class="woocommerce_rangement">Custom Field: <span>' . get_post_meta( $variations[ 'variation_id' ], 'rangement', true ) . '</span></div>';
return $variations;
}
And now, I would like to display this metadata in the mail sent to the administrator when he has a new order, but I don't want to display it on the payment page or in the customer's mail.
Could you help me to solve that ?
I have found how to display my custom field in cart and email with this code :
// display custom field in cart and email
add_filter( 'woocommerce_cart_item_name', 'showing_rgt_in_cart_items', 99, 3 );
function showing_rgt_in_cart_items( $item_name, $cart_item, $cart_item_key ) {
// The WC_Product object
$product = $cart_item['data'];
// Get the rangement
$rgt = get_post_meta( $product->get_id(), 'rangement', true );
// When rgt doesn't exist
if(empty($rgt)) return $item_name;
// Add the rangement field
$item_name .= '<br><small class="product-sku">' . __( "Rangement: ", "woocommerce") . $rgt . '</small>';
return $item_name;
}
But how could I only display it in admin email ?
I use the code, that on the product editing page shows the checkbox "Roast Level". When the manager clicks on this checkbox, a select box appears on the page of a single product, allowing the customer to select "Roast Level".
When selecting and adding a product to the cart, the selected value appears in the cart itself. This value is also shown on the checkout page, on the "Thank You" page, in the order, on the email notification, and on the order editing page in the admin panel.
Here is the code:
// Display Checkbox Field
add_action('woocommerce_product_options_general_product_data', 'roast_custom_field_add');
function roast_custom_field_add() {
global $post;
// Checkbox
woocommerce_wp_checkbox(
array(
'id' => '_roast_checkbox',
'label' => __('Roast Level', 'woocommerce'),
'description' => __('Enable roast level', 'woocommerce')
)
);
}
// Save Checkbox Field
add_action('woocommerce_process_product_meta', 'roast_custom_field_save');
function roast_custom_field_save($post_id) {
// Custom Product Checkbox Field
$roast_checkbox = isset($_POST['_roast_checkbox']) ? 'yes' : 'no';
update_post_meta($post_id, '_roast_checkbox', esc_attr($roast_checkbox));
}
/*---------------------------------------------------------------
*Display Select Box
---------------------------------------------------------------*/
add_action( 'woocommerce_before_add_to_cart_button', 'add_roast_custom_field', 0 );
function add_roast_custom_field() {
global $product;
// If is single product page and have the "roast_checkbox" enabled we display the field
if ( is_product() && $product->get_meta( '_roast_checkbox' ) === 'yes' ) {
echo '<div class="roast_select">';
$select = woocommerce_form_field( 'roast_custom_options', array(
'type' => 'select',
'class' => array('my-field-class form-row-wide'),
'label' => __('Roast Level'),
'required' => false,
'return' => false,
'options' => array(
'' => 'Please select',
'Blue' => 'Blue',
'Rare' => 'Rare',
'Medium Rare' => 'Medium Rare',
'Medium' => 'Medium',
'Medium Well' => 'Medium Well',
'Well Done' => 'Well Done'
)
), '' );
echo $select;
echo '</div>';
}
}
/*---------------------------------------------------------------
* Add as custom cart item data
---------------------------------------------------------------*/
add_filter( 'woocommerce_add_cart_item_data', 'add_custom_cart_item_data', 10, 21 );
function add_custom_cart_item_data($cart_item_data, $product_id, $variation_id ){
if( isset( $_POST['roast_custom_options'] ) ) {
$cart_item_data['roast_option'] = wc_clean( $_POST['roast_custom_options'] );
}
return $cart_item_data;
}
/*---------------------------------------------------------------
* Add custom fields values under cart item name in cart
---------------------------------------------------------------*/
add_filter( 'woocommerce_cart_item_name', 'roast_custom_field', 10, 21 );
function roast_custom_field( $item_name, $cart_item, $cart_item_key ) {
if( ! is_cart() )
return $item_name;
if( isset($cart_item['roast_option']) ) {
$item_name .= '<br /><div class="my-custom-class"><strong>' . __("Roast Level", "woocommerce") . ':</strong> ' . $cart_item['roast_option'] . '</div>';
}
return $item_name;
}
/*---------------------------------------------------------------
* Display roast custom fields values under item name in checkout
---------------------------------------------------------------*/
add_filter( 'woocommerce_checkout_cart_item_quantity', 'roast_custom_checkout_cart_item_name', 10, 21 );
function roast_custom_checkout_cart_item_name( $item_qty, $cart_item, $cart_item_key ) {
if( isset($cart_item['roast_option']) ) {
$item_qty .= '<br /><div class="my-custom-class"><strong>' . __("Roast Level", "woocommerce") . ':</strong> ' . $cart_item['roast_option'] . 'гр.</div>';
}
return $item_qty;
}
/*---------------------------------------------------------------
* Save chosen slelect field value to each order item as custom meta data and display it everywhere
---------------------------------------------------------------*/
add_action('woocommerce_checkout_create_order_line_item', 'save_order_item_product_fitting_color', 10, 21 );
function save_order_item_product_fitting_color( $item, $cart_item_key, $values, $order ) {
if( isset($values['roast_option']) ) {
$key = __('Roast Level', 'woocommerce');
$value = $values['roast_option'];
$item->update_meta_data( $key, $value ,$item->get_id());
}
}
add_action('wp_footer','add_footer_script');
function add_footer_script(){
?>
<script>
jQuery('#roast_custom_options').on('change',function(){
var roast_level = jQuery(this).val();
/*console.log(roast_level); */
var button = jQuery(this).closest('form').find('.add_to_cart_button'); console.log(button);
jQuery(button).attr('data-roast_custom_options',roast_level);
});
</script>
<?php
}
I need to add the “Roast Level” selection form to the quick view window, to the
content-product-quick-view.php file.
When adding code, errors appeared. The form does not show, or the "Add to Cart" button disappears.
global $product;
// If is single product page and have the "roast_checkbox" enabled we display the field
if ( $product->get_meta( '_roast_checkbox' ) === 'yes' ) {
echo '<div class="roast_select">';
$select = woocommerce_form_field( 'roast_custom_options', array(
'type' => 'select',
'class' => array('my-field-class form-row-wide'),
'label' => __('Roast Level'),
'required' => false,
'return' => false,
'options' => array(
'' => 'Please select',
'Blue' => 'Blue',
'Rare' => 'Rare',
'Medium Rare' => 'Medium Rare',
'Medium' => 'Medium',
'Medium Well' => 'Medium Well',
'Well Done' => 'Well Done'
)
), '' );
echo $select;
echo '</div>';
}
As a result, I could not put this code in the php file. Perhaps here need to add additional code. And I ask for your help.
Change your script in add_footer_script with this:
( function( $ ) {
$( document ).ready( function() {
$(document).on('change', '#roast_custom_options' ,function() {
$('.add_to_cart_button').data('roast_custom_options', this.value)
});
});
}( jQuery ) );
if you are using ajax, you must subscribe via the parent container or document. To pass custom field using data attribute.
That template already has the variable product and and you're redeclaring it. Remove global $product from it the code you added to content-product-quick-view.php file and you should be good to go.
I have a code that shows custom fields in the "General" tab on the product edit page.
After the manager has filled these fields, the data is displayed on the Archive/Category pages and in the Single Product page.
Also, these fields are in the cart and on the checkout page.
Here is my code:
// Display Fields using WooCommerce Action Hook
add_action( 'woocommerce_product_options_general_product_data', 'woocom_general_product_data_custom_field' );
function woocom_general_product_data_custom_field() {
// Create a custom text field
// Custom Weight Field
woocommerce_wp_text_input(
array(
'id' => '_custom_weight',
'label' => __( 'Weight dishes', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( '', 'woocommerce' )
)
);
// Calories Field
woocommerce_wp_text_input(
array(
'id' => '_сalories',
'label' => __( 'Calories', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => 'false',
'description' => __( '', 'woocommerce' )
)
);
// Ingredients Field
woocommerce_wp_textarea_input(
array(
'id' => '_ingredients',
'label' => __( 'Ingredients', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( '', 'woocommerce' )
)
);
}
// Hook to save the data value from the custom fields
add_action( 'woocommerce_process_product_meta', 'woocom_save_general_proddata_custom_field' );
// Hook callback function to save custom fields information
function woocom_save_general_proddata_custom_field( $post_id ) {
// Save Custom Weight Field
$custom_weight = $_POST['_custom_weight'];
if( ! empty( $custom_weight ) ) {
update_post_meta( $post_id, '_custom_weight', esc_attr( $custom_weight ) );
} else {
delete_post_meta( $post_id, '_custom_weight' );
}
// Save Calories Field
$сalories = $_POST['_сalories'];
if( ! empty( $сalories ) ) {
update_post_meta( $post_id, '_сalories', esc_attr( $сalories ) );
} else {
delete_post_meta( $post_id, '_сalories' );
}
// Save Ingredients Field
$ingredients = $_POST['_ingredients'];
if( ! empty( $ingredients ) ) {
update_post_meta( $post_id, '_ingredients', esc_html( $ingredients ) );
} else {
delete_post_meta( $post_id, '_ingredients' );
}
}
// Displaying the custom field value (on single product pages under short description)
add_action('woocommerce_before_add_to_cart_form', 'display_custom_meta_field_value', 25 );
add_action('woocommerce_after_shop_loop_item', 'display_custom_meta_field_value', 25 );
function display_custom_meta_field_value() {
global $product;
$custom_weight = get_post_meta( $product->get_id(),'_custom_weight', true );
if( ! empty( $custom_weight ) )
echo '<p id="value-on-single-product">' . 'Weight: ' . $custom_weight . 'g' . '</p>';
$сalories = get_post_meta( $product->get_id(),'_сalories', true );
if( ! empty( $сalories ) )
echo '<p id="value-on-single-product">' . 'Calories: ' . $сalories . ' kcal.' . '</p>';
$ingredients = get_post_meta( $product->get_id(),'_ingredients', true );
if( ! empty( $ingredients ) )
echo '<p id="value-on-single-product">' . 'Ingredients: ' . $ingredients . '</p>';
}
// Render the custom product field in cart and checkout
add_filter( 'woocommerce_get_item_data', 'woocom_custom_fields_cart', 10, 2 );
function woocom_custom_fields_cart( $cart_data, $cart_item )
{
$custom_items = array();
if( !empty( $cart_data ) )
$custom_items = $cart_data;
// Get the product ID
$product_id = $cart_item['product_id'];
if( $custom_field_value = get_post_meta( $product_id, '_custom_weight', true ) )
$custom_items[] = array(
'name' => __( 'Weight', 'woocommerce' ),
'value' => $custom_field_value,
'display' => $custom_field_value . 'g',
);
return $custom_items;
}
But unfortunately, it’s impossible for me to add these custom fields after the product name on the Thank You page, in the E-mail and on the order editing page.
I also have doubts whether the above code is correct, although everything works.
I will be glad for your help!
I have revisited your code and made some changes, adding the necessary code to display your custom fields data on cart, checkout, order received, my account order view and on email notifications (for Woocommerce 3+):
// Backend: Display additional product fields
add_action( 'woocommerce_product_options_general_product_data', 'add_fields_to_options_general_product_data' );
function add_fields_to_options_general_product_data() {
// Custom Weight Field
woocommerce_wp_text_input( array(
'id' => '_custom_weight',
'label' => __( 'Weight dishes', 'woocommerce' ),
));
// Calories Field
woocommerce_wp_text_input( array(
'id' => '_сalories',
'label' => __( 'Calories', 'woocommerce' ),
));
// Ingredients Field
woocommerce_wp_textarea_input( array(
'id' => '_ingredients',
'label' => __( 'Ingredients', 'woocommerce' ),
));
}
// Backend: Save the data value from the custom fields
add_action( 'woocommerce_admin_process_product_object', 'save_admin_product_custom_fields_values' );
function save_admin_product_custom_fields_values( $product ) {
// Save Custom Weight Field
if( isset( $_POST['_custom_weight'] ) ) {
$product->update_meta_data( '_custom_weight', sanitize_text_field( $_POST['_custom_weight'] ) );
}
// Save Calories Field
if( isset( $_POST['_сalories'] ) ) {
$product->update_meta_data( '_сalories', sanitize_text_field( $_POST['_сalories'] ) );
}
// Save Ingredients Field
if( isset( $_POST['_ingredients'] ) ) {
$product->update_meta_data( '_ingredients', sanitize_textarea_field( $_POST['_ingredients'] ) );
}
}
// Display product custom fields values on single product pages under short description and on archive pages
add_action('woocommerce_before_add_to_cart_form', 'display_custom_meta_field_value', 25 );
add_action('woocommerce_after_shop_loop_item', 'display_custom_meta_field_value', 25 );
function display_custom_meta_field_value() {
global $product;
if( $custom_weight = $product->get_meta('_custom_weight') )
echo '<p id="value-on-single-product">' . __("Weight:", "woocommerce") . ' ' . $custom_weight . 'g' . '</p>';
if( $сalories = $product->get_meta('_сalories') )
echo '<p id="value-on-single-product">' . __("Calories:", "woocommerce") . ' ' . $сalories . ' kcal.' . '</p>';
if( $ingredients = $product->get_meta('_ingredients') )
echo '<p id="value-on-single-product">' . __("Ingredients:", "woocommerce") . ' ' . $ingredients . '</p>';
}
// Add custom fields values under cart item name in cart
add_filter( 'woocommerce_cart_item_name', 'custom_cart_item_name', 10, 3 );
function custom_cart_item_name( $item_name, $cart_item, $cart_item_key ) {
if( ! is_cart() )
return $item_name;
if( $value1 = $cart_item['data']->get_meta('_custom_weight') ) {
$item_name .= '<br><span class="custom-field"><strong>' . __("Weight", "woocommerce") . ':</strong> ' . $value1 . 'g</span>';
}
if( $value2 = $cart_item['data']->get_meta('_сalories') ) {
$item_name .= '<br><span class="custom-field"><strong>' . __("Calories", "woocommerce") . ':</strong> ' . $value2 . 'kcal</span>';
}
if( $value3 = $cart_item['data']->get_meta('_ingredients') ) {
$item_name .= '<br><span class="custom-field"><strong>' . __("Ingredients", "woocommerce") . ':</strong> <br>' . $value3 . '</span>';
}
return $item_name;
}
// Display custom fields values under item name in checkout
add_filter( 'woocommerce_checkout_cart_item_quantity', 'custom_checkout_cart_item_name', 10, 3 );
function custom_checkout_cart_item_name( $item_qty, $cart_item, $cart_item_key ) {
if( $value1 = $cart_item['data']->get_meta('_custom_weight') ) {
$item_qty .= '<br><span class="custom-field"><strong>' . __("Weight", "woocommerce") . ':</strong> ' . $value1 . 'g</span>';
}
if( $value2 = $cart_item['data']->get_meta('_сalories') ) {
$item_qty .= '<br><span class="custom-field"><strong>' . __("Calories", "woocommerce") . ':</strong> ' . $value2 . 'kcal</span>';
}
if( $value3 = $cart_item['data']->get_meta('_ingredients') ) {
$item_qty .= '<br><span class="custom-field"><strong>' . __("Ingredients", "woocommerce") . ':</strong> <br>' . $value3 . '</span>';
}
return $item_qty;
}
// Display custom fields values on orders and email notifications
add_filter( 'woocommerce_order_item_name', 'custom_order_item_name', 10, 2 );
function custom_order_item_name( $item_name, $item ) {
$product = $item->get_product();
if( $value1 = $product->get_meta('_custom_weight') ) {
$item_name .= '<br><span class="custom-field"><strong>' . __("Weight", "woocommerce") . ':</strong> ' . $value1 . 'g</span>';
}
if( $value2 = $product->get_meta('_сalories') ) {
$item_name .= '<br><span class="custom-field"><strong>' . __("Calories", "woocommerce") . ':</strong> ' . $value2 . 'kcal</span>';
}
if( $value3 = $product->get_meta('_ingredients') ) {
$item_name .= '<br><span class="custom-field"><strong>' . __("Ingredients", "woocommerce") . ':</strong> <br>' . $value3 . '</span>';
}
return $item_name;
}
Code goes on function.php file of your active child theme (or active theme). Tested and works.
On cart page:
On checkout page:
On order received page:
On email notifications: