I have built an e-commerce site using Woocommerce. I would like to add two more check boxes below the terms and conditions. I have searched everywhere for a working solution and the only thing that I found is a commercial plugin.
How to add custom checkout fields (2 checkboxes) below the terms and conditions programmatically?
Location of the terms and condition screenshot:
The 1st hooked function displays the 2 additional checkout fields
The 2nd hooked function will check that both checkboxes are "selected" to allow checkout, displaying a custom error notice if not…
The code:
add_action('woocommerce_checkout_before_terms_and_conditions', 'checkout_additional_checkboxes');
function checkout_additional_checkboxes( ){
$checkbox1_text = __( "My first checkbox text", "woocommerce" );
$checkbox2_text = __( "My Second checkbox text", "woocommerce" );
?>
<p class="form-row custom-checkboxes">
<label class="woocommerce-form__label checkbox custom-one">
<input type="checkbox" class="woocommerce-form__input woocommerce-form__input-checkbox input-checkbox" name="custom_one" > <span><?php echo $checkbox1_text; ?></span> <span class="required">*</span>
</label>
<label class="woocommerce-form__label checkbox custom-two">
<input type="checkbox" class="woocommerce-form__input woocommerce-form__input-checkbox input-checkbox" name="custom_two" > <span><?php echo $checkbox2_text; ?></span> <span class="required">*</span>
</label>
</p>
<?php
}
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['custom_one'] )
wc_add_notice( __( 'You must accept "My first checkbox".' ), 'error' );
if ( ! $_POST['custom_two'] )
wc_add_notice( __( 'You must accept "My second checkbox".' ), 'error' );
}
Code goes in function.php file of your active child theme (active theme).
Tested and works.
Related
I want to add a conditional requirement on the Checkout page. Because a lot of people fill the Name of Company without they are a company. And I want to add to the "billing_company" field a conditional where if the customer fill the "billing_company" field need to be fill the "woocommerce_eu_vat_number" field too. The problem is those two fields are optionals. But I want to do them as required if billing_company /billing_vat_number is filled. Is it possible?
Field Codes in HTML:
<p class="form-row form-row-wide" id="billing_company_field" data-priority="30">
<label for="billing_company" class="">Company name <span class="optional">(optional)</span></label>
<span class="woocommerce-input-wrapper czr-focus">
<input type="text" class="input-text czr-focusable" name="billing_company" id="billing_company" placeholder="" value="" autocomplete="organization">
</span>
</p>
<p class="form-row form-row-wide" id="woocommerce_eu_vat_number_field" data-priority="120">
<label for="woocommerce_eu_vat_number" class="">VAT number (companies) <span class="optional">(optional)</span></label>
<span class="woocommerce-input-wrapper czr-focus">
<input type="text" class="input-text czr-focusable" name="billing_vat_number" id="woocommerce_eu_vat_number" placeholder="" value="">
</span>
</p>
I want a code something like this. Sorry because I can understand more or less php code but I don't know how to create it from zero. T_T
<?php
function custom_required_vat_billing_fields() {
if( !empty ('billing_company' ) {
set ($fields['billing']['billing_vat_number'] = class [REQUIRED=true] );)
} if not {
wc_add_notice(__('Please enter a VAT number if you are a company'), 'error');
}
};
return $fields;
}
add_filter('woocommerce_checkout_fields','custom_required_vat_billing_fields');
?>
If checkbox is checked, then field company ID is required. Write code below to your child themes functions.php file and change ID of elements:
wi_as_company is ID of checkbox and
billing_company_wi_id is ID of required field if checkbox is checked
add_action( 'woocommerce_checkout_process', 'afm_validation' );
function afm_validation() {
if ( isset($_POST['wi_as_company']) && isset($_POST['billing_company_wi_id']) && empty($_POST['billing_company_wi_id']) ) {
wc_add_notice( __("Please fill company ID"), "error" );
}
}
So I was able to limit the zip code length limit to 5 on the user's shipping/billing info on their account page as well as the checkout page using this code in my functions.php:
function my_wc_custom_billing_fields( $fields ) {
$fields['billing_postcode']['maxlength'] = 5;
return $fields;
}
add_filter( 'woocommerce_billing_fields', 'my_wc_custom_billing_fields' );
function my_wc_custom_shipping_fields( $fields ) {
$fields['shipping_postcode']['maxlength'] = 5;
return $fields;
}
add_filter( 'woocommerce_shipping_fields', 'my_wc_custom_shipping_fields' );
However, I still am able to enter past the limit in the zip code box on the CART page. You are able to change your address on the cart page and if you click "go to checkout" after typing more than 5 digits, it will allow the form to fill in with those additional digits on the checkout page. I want the zip code box on the CART page to work the same as it does on the other pages.
Thank you for taking to the time to read this. I hope to hear from someone soon!
------- >EDIT: FIGURED IT OUT!
Instead of creating a filter inside my functions.php, I directly edited the woocommerce/templates/cart/shipping-calculator.php file.
In this piece of code:
<?php if ( apply_filters( 'woocommerce_shipping_calculator_enable_postcode', true ) ) : ?>
<p class="form-row form-row-wide" id="calc_shipping_postcode_field">
<input type="text" class="input-text" value="<?php echo esc_attr( WC()->customer->get_shipping_postcode() ); ?>" placeholder="<?php esc_attr_e( 'Postcode / ZIP', 'woocommerce' ); ?>" name="calc_shipping_postcode" id="calc_shipping_postcode" />
</p>
<?php endif; ?>
I simply added "maxlength="5" in the line.
<input type="text" class="input-text" maxlength="5" value="
I hope this helps someone along the way! :)
In woocommerce, after creating and registering some custom account fields in a custom php file using the following code:
<label for="reg_shipping_phone"> ... </label>
<input class="..." id="reg_shipping_phone" name="shipping_phone"
type="tel" pattern="[a-z0-9.-]{6,40}"
title=" ... " placeholder=" ... "
value="<?php esc_attr_e( $_POST['shipping_phone'] ); ?>" />
and in my theme's function.php file:
//save on admin/&frontend on change
add_action( 'personal_options_update', 'woo_save_extra_register_fields' );
add_action( 'woocommerce_save_account_details', 'woo_save_extra_register_fields' );
// Save extra registration fields data on from
add_action( 'woocommerce_created_customer', 'woo_save_extra_register_fields' );
function woo_save_extra_register_fields( $customer_id )
{
if( isset( $_POST['shipping_phone'] ) ) {
update_user_meta( $customer_id, 'shipping_phone', $_POST['shipping_phone'] );
}
}
I would like to implement this "Shipping phone" field in the correct position on Backend User profile pages inside the "Customer's shipping address" section table
How can I insert additional fields in the "Customer's shipping address" section table?
For example I have tried the following *(but 11,5 is wrong...)*:
add_action( 'show_user_profile', 'extra_profile_fields',***11,5*** );
add_action( 'edit_user_profile', 'extra_profile_fields',***11,5*** );
function extra_profile_fields( $user ) { ?>
<h3>NAME OF TABLE</h3>
<table class="form-table">
<tr>
<th><label for="shipping_phone">SHIPPING PHONE</label></th>
<td>
<input type="text" name="shipping_phone" id="shipping_phone" value="<?php echo esc_attr( $user->shipping_phone); ?>" class="regular-text" />
</td>
</tr>
>
</table>
<?php }
Any help is appreciated.
If you want to include your custom "Shipping phone" field in Backend User profile under "Customer's shipping address" section, you will use the following instead:
add_filter( 'woocommerce_customer_meta_fields', 'filter_add_customer_meta_fields', 10, 1 );
function filter_add_customer_meta_fields( $args ) {
$args['shipping']['fields']['shipping_phone'] = array(
'label' => __( 'Shipping phone', 'woocommerce' ),
'description' => '',
);
return $args;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
This little code snippet will do it all. If you change the value in this "Shipping phone" field, it will be updated without needing any additional code.
Trying to add a field for Woocommerce billing_phone to the my-account/edit-account/. It is present within the update address pages but when adding to the form-edit-account.php it does not update.
Currently adding by following the same code as the other fields, such as first_name:
<input type="text" class="form-control woocommerce-Input woocommerce-Input--phone input-text" name="billing_phone" id="billing_phone" value="<?php echo esc_attr( $user->billing_phone ); ?>" />
Image of form with billing_phone being shown as a value:
But upon updating with new number it is not changed…
How can I make this being saved/updated?
You need to add a custom function hooked in woocommerce_save_account_details action hook:
add_action( 'woocommerce_save_account_details', 'my_account_saving_billing_phone', 10, 1 );
function my_account_saving_billing_phone( $user_id ) {
$billing_phone = $_POST['billing_phone'];
if( ! empty( $billing_phone ) )
update_user_meta( $user_id, 'billing_phone', sanitize_text_field( $billing_phone ) );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested on WooCommerce version 3+ and works. The data will be updated and displayed correctly.
Your complete billing phone field code in form-edit-account.php should be something like:
<?php function field_phone(){
$user = wp_get_current_user();
?>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="billing_phone"><?php _e( 'Phone', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="text" class="woocommerce-Input woocommerce-Input--phone input-text" name="billing_phone" id="billing_phone" value="<?php echo esc_attr( $user->billing_phone ); ?>" />
</p> <?php } ?>
My Environment is:
- WordPress 4.7.4
- Debian Linux 8
- WooCommerce 3.0.5
- 256M Memory
I've tried a number of solutions including:
Add custom variable to cart content
WooCommerce Show Attributes plugin
However, I'm still not getting the right result and time is of the essence at this point of this project. A precision, I have the same price for all attribute values…
I created a custom single-product.php tempalte with a custom form:
<form id="add-product-form" class="add-product-form form-horizontal" method="post" action="">
<input name="add-to-cart" value="15709" type="hidden">
<div class="form-group color-dropdown">
<label class="col-sm-3 control-label">Color</label>
<select id="color-options" class="col-sm-9 color-select" name="color" required="">
<option value="auburn">Auburn</option>
<option value="black">Black</option>
<option value="mahogany-ash">Mahogany Ash</option>
<option value="mocha">Mocha</option> </select>
</div>
<div class="form-group quantity-area">
<label class="col-sm-3 control-label">Qty.</label>
<input name="quantity" id="quantity" maxlength="2" class="col-sm-9 quantity-input" required="" type="text">
</div>
<button id="submit-to-cart" value="Add to Cart" class="btn btn-a2c submit" name="submit" type="submit"><i class="fa fa-plus" aria-hidden="true"></i> Add to Cart</button>
</form>
This form uses an AJAX post method and adds to cart as intended.
However:
I'm not seeing the color they chose listed on the WC Cart page
I'm not seeing the color they chose listed on the WC Checkout page
I'm not seeing the color they chose on the corresponding emails. I know I have to edit email-order-items.php but I don't know the right approach here.
My question:
So How can I add a Custom Attribute selected value to Cart, Checkout, Order and email notification?
I know I can take the Variable product approach, but even at 256M memory, the Variations menu in the Variable Product area constantly spins so I can never get to this area to Add Variations.
Instead of overriding your template single-product.php, it is better to use the original hook do_action('woocommerce_before_add_to_cart_button'); that are made to inject code in it through some custom hooked function.
As I have understood, you don't need to use a variable product. You want to use a single product that is going to display a custom selector field in which you set an existing "Color" attribute with the chosen values for this product.
Here is that hooked function:
// Add the custom field selector based on attribute "Color" values set in the simple product
add_action( 'woocommerce_before_add_to_cart_button', 'action_before_add_to_cart_button' );
function action_before_add_to_cart_button(){
global $product;
foreach($product->get_attributes() as $attribute_slug => $attribute_obj){
if($attribute_slug == 'pa_color'){
echo '<div class="form-group color-dropdown">
<label class="col-sm-3 control-label" for="custom_pa_color">'. __('Color', 'woocommerce') .'</label>
<select id="custom_pa_color" class="col-sm-9 color-select" name="custom_pa_color" required="">';
foreach( $attribute_obj->get_terms() as $term_obj){
$term_id = $term_obj->id;
$term_name = $term_obj->name;
$term_slug = $term_obj->slug;
echo '<option value="'.$term_slug.'">'.$term_name.'</option>';
}
echo '</select>
</div>';
}
}
}
Then as you want to pass in cart item the selected "Color" attribute "value" when product is added to cart and finally to display it in cart, checkout, order and email notifications here is the code you need:
// Save the custom product custom field data in Cart item
add_action( 'woocommerce_add_cart_item_data', 'save_in_cart_my_custom_product_field', 10, 2 );
function save_in_cart_my_custom_product_field( $cart_item_data, $product_id ) {
if( isset( $_POST['custom_pa_color'] ) ) {
$cart_item_data[ 'custom_pa_color' ] = $_POST['custom_pa_color'];
// When add to cart action make an unique line item
$cart_item_data['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'custom_data', $_POST['custom_pa_color'] );
}
return $cart_item_data;
}
// Render the custom product custom field in cart and checkout
add_filter( 'woocommerce_get_item_data', 'render_custom_field_meta_on_cart_and_checkout', 10, 2 );
function render_custom_field_meta_on_cart_and_checkout( $cart_data, $cart_item ) {
$custom_items = array();
if( !empty( $cart_data ) )
$custom_items = $cart_data;
if( $custom_field_value = $cart_item['custom_pa_color'] )
$custom_items[] = array(
'name' => __( 'Color', 'woocommerce' ),
'value' => $custom_field_value,
'display' => $custom_field_value,
);
return $custom_items;
}
// Add the the product custom field as item meta data in the order + email notifications
add_action( 'woocommerce_add_order_item_meta', 'tshirt_order_meta_handler', 10, 3 );
function tshirt_order_meta_handler( $item_id, $cart_item, $cart_item_key ) {
$custom_field_value = $cart_item['custom_pa_color'];
// We add the custom field value as an attribute for this product
if( ! empty($custom_field_value) )
wc_update_order_item_meta( $item_id, 'pa_color', $custom_field_value );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code works and is tested for WooCommerce version from 2.5 to 3.0+
In your template
You will have to remove the selector code and to re-insert the oringinal hook:
<form id="add-product-form" class="add-product-form form-horizontal" method="post" action="">
<?php
// Here we re-insert the original hook
do_action('woocommerce_before_add_to_cart_button');
?>
<div class="form-group quantity-area">
<label class="col-sm-3 control-label">Qty.</label>
<input name="quantity" id="quantity" maxlength="2" class="col-sm-9 quantity-input" required="" type="text">
</div>
<button id="submit-to-cart" value="Add to Cart" class="btn btn-a2c submit" name="submit" type="submit"><i class="fa fa-plus" aria-hidden="true"></i> Add to Cart</button>
</form>
Related answer: Saving a product custom field and displaying it in cart page