How to move the create account checkbox on Woocommerce checkout page - php

On my current checkout page I have the "create account" checkbox after the email field. What I am attempting to do is to move the create account checkbox inline and next to the email field. So I would have the email field on the left and the created account checkbox to the right.
I am able to move the create account checkbox but I just cannot figure out how to achieve the look I described. Any help would be appreciated. Thank you!
Checkout page here :
https://www.dailymutt.com/checkout/

This can be done adding a new similar checkbox field to billing form and hiding the real checkbox one with CSS. Then with the help of jQuery, you can trigger the hidden checkbox from the duplicated one.
Here is that code:
// CSS rules
add_action( 'woocommerce_before_checkout_billing_form', 'move_checkout_create_an_account_css' );
function move_checkout_create_an_account_css() {
if( ! is_user_logged_in() ) :
?><style>
.woocommerce-account-fields label.woocommerce-form__label-for-checkbox {display: none !important;}
#account_cb_field {margin-top: 32px;}
#account_cb_field input {margin-right: 6px;}
</style>
<?php
endif;
}
// Add a checkbox to billing section
add_filter( 'woocommerce_checkout_fields', 'move_checkout_create_an_account_checkbox' );
function move_checkout_create_an_account_checkbox( $fields ) {
if( ! is_user_logged_in() ) {
// Make email field on half on left side
$fields['billing']['billing_email']['class'] = array('form-row-first');
// Custom checkbox on half right side
$fields['billing']['account_cb'] = array(
'type' => 'checkbox',
'label' => __("Create an account?", "woocommerce"),
'class' => array('form-row-last'),
);
}
return $fields;
}
// remove "(optional)" from the new checkbox
add_filter( 'woocommerce_form_field' , 'remove_checkout_optional_fields_label', 10, 4 );
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) {
// Only on checkout page
if ( is_checkout() && ! is_wc_endpoint_url() && $key === 'account_cb' ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// The jQuery code
add_action( 'wp_footer', 'move_checkout_create_an_account_js' );
function move_checkout_create_an_account_js() {
if ( ! is_user_logged_in() && is_checkout() && ! is_wc_endpoint_url() ) :
?><script>
(function($){
$('input[name=account_cb]').on( 'click', function() {
$('input[name=createaccount]').trigger('click');
});
})(jQuery);
</script>
<?php
endif;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

Related

WooCommerce custom create account checkbox on checkout

We just moved and merged the WooCommerce account password field on the checkout page from the "Account" group to the "Billing" field group. This works nicely. Also, we create a new checkbox field and add this to the billing section. Without that, the "Create an account" checkbox will still be at the default position. To do so, we created a new checkbox with jQuery.
Thanks to the following articles:
How to move the create account checkbox on Woocommerce checkout page
Reordering checkout fields in WooCommerce 3
With our current code, the moved password field is always visible. We want to have it the same way as WooCommerce default works. This means the password field should only be visible when the checkbox is active. WooCommerce by default has an excellent hide & Show CSS in place. However, I'm not able to use the identical CSS (or maybe script?!).
How can we connect the custom checkbox with the account password field?
// Move Account password field into billing section
function move_password_field($checkout_fields){
// Move Account Password into Billing
$checkout_fields['billing']['account_password'] = $checkout_fields['account']['account_password'];
// Remove Password from Billing
unset($checkout_fields['account']['account_password']);
return $checkout_fields;
}
add_filter('woocommerce_checkout_fields', 'move_password_field', 999);
// CSS rules
add_action( 'woocommerce_before_checkout_billing_form', 'move_checkout_create_an_account_css' );
function move_checkout_create_an_account_css() {
if( ! is_user_logged_in() ) :
?><style>
.woocommerce-account-fields label.woocommerce-form__label-for-checkbox {display: none !important;}
#account_cb_field {margin-top: 32px;}
#account_cb_field input {margin-right: 6px;}
</style>
<?php
endif;
}
// Add a checkbox to billing section
add_filter( 'woocommerce_checkout_fields', 'move_checkout_create_an_account_checkbox' );
function move_checkout_create_an_account_checkbox( $fields ) {
if( ! is_user_logged_in() ) {
// Make email field on half on left side
$fields['billing']['billing_email']['class'] = array('form-row-wide');
// Custom checkbox on half right side
$fields['billing']['account_cb'] = array(
'type' => 'checkbox',
'label' => __("Create an account?", "woocommerce"),
'class' => array('form-row-wide'),
);
}
return $fields;
}
// remove "(optional)" from the new checkbox
add_filter( 'woocommerce_form_field' , 'remove_checkout_optional_fields_label', 10, 4 );
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) {
// Only on checkout page
if ( is_checkout() && ! is_wc_endpoint_url() && $key === 'account_cb' ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// The jQuery code
add_action( 'wp_footer', 'move_checkout_create_an_account_js' );
function move_checkout_create_an_account_js() {
if ( ! is_user_logged_in() && is_checkout() && ! is_wc_endpoint_url() ) :
?><script>
(function($){
$('input[name=account_cb]').on( 'click', function() {
$('input[name=createaccount]').trigger('click');
});
})(jQuery);
</script>
<?php
endif;
}

Allow guest checkout for specific products only in WooCommerce

The following code add a custom field to admin product settings to manage guest checkout at product level:
// Display Guest Checkout Field
add_action( 'woocommerce_product_options_general_product_data', 'woo_add_custom_general_fields' );
function woo_add_custom_general_fields() {
global $woocommerce, $post;
echo '<div class="options_group">';
// Checkbox
woocommerce_wp_checkbox( array(
'id' => '_allow_guest_checkout',
'wrapper_class' => 'show_if_simple',
'label' => __('Checkout', 'woocommerce' ),
'description' => __('Allow Guest Checkout', 'woocommerce' )
) );
echo '</div>';
}
// Save Guest Checkout Field
add_action( 'woocommerce_process_product_meta', 'woo_add_custom_general_fields_save' );
function woo_add_custom_general_fields_save( $post_id ){
$woocommerce_checkbox = isset( $_POST['_allow_guest_checkout'] ) ? 'yes' : 'no';
update_post_meta( $post_id, '_allow_guest_checkout', $woocommerce_checkbox );
}
// Enable Guest Checkout on Certain products
add_filter( 'pre_option_woocommerce_enable_guest_checkout', 'enable_guest_checkout_based_on_product' );
function enable_guest_checkout_based_on_product( $value ) {
if ( WC()->cart ) {
$cart = WC()->cart->get_cart();
foreach ( $cart as $item ) {
if ( get_post_meta( $item['product_id'], '_allow_guest_checkout', true ) == 'yes' ) {
$value = "yes";
} else {
$value = "no";
break;
}
}
}
return $value;
}
But it doesn't work actually. What I am doing wrong? How can I fix it?
I am trying to allow guest purchases for specific products. The admin custom field display and save custom field value is working (the 2 first functions), But login/register never comes up on checkout page, even if there are products in cart that doesn't allow guest checkout.
The filter hook enable_guest_checkout_based_on_product doesn't exist anymore and has been replaced by another hook a bit different.
So your code is going to be:
add_filter( 'woocommerce_checkout_registration_required', 'change_tax_class_user_role', 900 );
function change_tax_class_user_role( $registration_required ) {
if ( ! WC()->cart->is_empty() ) {
$registration_required = false; // Initializing (allowing guest checkout by default)
// Loop through cart items
foreach ( WC()->cart->get_cart() as $item ) {
// Check if there is any item in cart that has not the option "Guest checkout allowed"
if ( get_post_meta( $item['product_id'], '_allow_guest_checkout', true ) !== 'yes' ) {
return true; // Found: Force checkout user registration and exit
}
}
}
return $registration_required;
}
Code goes in functions.php file of your active child theme (or active theme). It should works.
Related continuation: Redirection for non checkout guest allowed in WooCommerce

Show/Hide WooCommerce Shipping Rates Based on Radio Buttons

I've been looking for a solution to this for a while now... I am trying to show or hide specific shipping rates based on a radio button option added to the Woocommerce checkout page. But I don't know anything about Ajax & JQuery which I believe it requires.
Basically if a user selects radio option_1 it will ONLY show 'flat_rate:1' & 'flat_rate:2'. If the user selects radio option_2 it will ONLY show 'flat_rate:3' & 'flat_rate:4'
Click here for example of checkout screen
Here is the code for my radio buttons displayed on checkout page:
add_action( 'woocommerce_review_order_before_payment','tc_checkout_radio_choice' );
function tc_checkout_radio_choice() {
$businesstype = array(
'type' => 'radio',
'class' => array( 'business_residential' ),
'required' => true,
'options' => array(
'option_1' => 'Business',
'option_2' => 'Residential',
),
);
echo '<div id="checkout-radio">';
echo '<h3>Select Your Business Type</h3>';
woocommerce_form_field( 'radio_choice', $businesstype );
echo '</div>';
}
The closest example I've seen comes from an answer provided by 'LoicTheAztec' in this post here: Show/hide shipping methods based on a WooCommerce checkout field value
I'm completely lost with this and the more I try to solve it, the more I get confused.
Here is the correct way to show hide shipping methods based on multiple radio buttons choice on checkout page, that requires to use PHP, Ajax, jQuery and WC Session.
When "Business" radio button is selected (default choice), flat_rate:3 and flat_rate:4 shipping methods will be hidden, so customer will only be able to choose flat_rate:1 or flat_rate:2 shipping methods.
If "Residential" radio button is selected then flat_rate:1 and flat_rate:2 shipping methods will be hidden, so customer will only be able to choose flat_rate:3 or flat_rate:4 shipping methods.
The code:
// Display a Custom radio buttons fields for shipping options
add_action( 'woocommerce_review_order_before_payment','checkout_customer_type_radio_buttons' );
function checkout_customer_type_radio_buttons() {
$field_id = 'customer_type';
echo '<div id="customer-type-radio">';
echo '<h3>' . __("Select Your Business Type", "woocommerce") . '</h3>';
// Get the selected radio button value (if selected)
$field_value = WC()->session->get( $field_id );
// Get customer selected value on last past order
if( empty($field_value) )
$field_value = WC()->checkout->get_value( $field_id );
// The default value fallback
if( empty($field_value) )
$field_value = 'Business';
woocommerce_form_field( $field_id, array(
'type' => 'radio',
'class' => array( $field_id ),
'required' => true,
'options' => array(
'Business' => __('Business', 'woocommerce'),
'Residential' => __('Residential', 'woocommerce'),
),
), $field_value );
echo '</div>';
}
// Conditionally show/hide shipping methods
add_filter( 'woocommerce_package_rates', 'shipping_package_rates_filter_callback', 100, 2 );
function shipping_package_rates_filter_callback( $rates, $package ) {
$customer_type = WC()->session->get( 'customer_type' ); // Get the customere type
if ( $customer_type === 'Business' ) {
if( isset( $rates['flat_rate:3'] ) )
unset( $rates['flat_rate:3'] );
if( isset( $rates['flat_rate:4'] ) )
unset( $rates['flat_rate:4'] );
}
elseif ( $customer_type === 'Residential' ) {
if( isset( $rates['flat_rate:1'] ) )
unset( $rates['flat_rate:1'] );
if( isset( $rates['flat_rate:2'] ) )
unset( $rates['flat_rate:2'] );
}
return $rates;
}
// function that gets the Ajax data
add_action( 'wp_ajax_get_customer_type', 'wc_get_customer_type' );
add_action( 'wp_ajax_nopriv_get_customer_type', 'wc_get_customer_type' );
function wc_get_customer_type() {
$field_id = 'customer_type';
if ( isset($_POST[$field_id]) && ! empty($_POST[$field_id]) ){
WC()->session->set($field_id, $_POST[$field_id] );
}
echo json_encode( WC()->session->get( $field_id ) );
die(); // (required)
}
// The Jquery Ajax script
add_action( 'wp_footer', 'custom_checkout_ajax_jquery_script' );
function custom_checkout_ajax_jquery_script() {
$field_id = 'customer_type';
if( WC()->session->__isset($field_id) )
WC()->session->__unset($field_id);
// Only on checkout when billing company is not defined
if( is_checkout() && ! is_wc_endpoint_url() ):
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;
var fieldId = 'p#customer_type_field input';
function userTypeTriggerAjax( customerType ){
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'get_customer_type',
'customer_type': customerType,
},
success: function (result) {
// Trigger refresh checkout
$('body').trigger('update_checkout');
console.log(result);
}
});
}
// On start
if( $(fieldId).val() != '' ) {
userTypeTriggerAjax( $(fieldId).val() );
}
// On change
$(fieldId).change( function () {
userTypeTriggerAjax( $(this).val() );
});
});
</script>
<?php
endif;
}
// Enabling, disabling and refreshing session shipping methods data
add_action( 'woocommerce_checkout_update_order_review', 'refresh_shipping_methods', 10, 1 );
function refresh_shipping_methods( $post_data ){
$bool = true;
if ( in_array( WC()->session->get('customer_type' ), ['Business', 'Residential'] ) )
$bool = false;
// Mandatory to make it work with shipping methods
foreach ( WC()->cart->get_shipping_packages() as $package_key => $package ){
WC()->session->set( 'shipping_for_package_' . $package_key, $bool );
}
WC()->cart->calculate_shipping();
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Code based on this related threads:
Remove shipping cost if custom checkbox is checked in WooCommerce Checkout
Show/hide shipping methods based on a WooCommerce checkout field value
If anyone wants to know how to make this a required option with an error notification before payment, this is what I did...
To de-select the radio buttons I removed the value from:
//if( empty($field_value) )
$field_value = '';
And added this code to the checkout process at the end of the code from Loic, which adds a notification message if a radio button has not been selected:
// Show notice if customer does not select a business type
add_action( 'woocommerce_checkout_process', 'business_type_error_message' );
function business_type_error_message() {
if ( ! (int) isset( $_POST['customer_type'] ) ) {
wc_add_notice( __( 'Please select an order type to calculate the correct shipping and proceed with your order.' ), 'error' );
}
}
Hope this helps others out there!

Add a custom checkbox to woocommerce quickedit in admin panel

I tried to create a checkbox in the product edit site in woocommerce, which allows me to enable/disable a custom badge banner showed only on specific products. I got it working in the normal edit page, but also want to show the checkbox in the product quickedit panel.
I got it working in the product edit page with the code showing below. This was pretty simple as it was working out of the box.
/* 1. Add new checkbox to product edit page (General tab) */
add_action('woocommerce_product_options_general_product_data', 'bbloomer_add_badge_checkbox_to_products');
function bbloomer_add_badge_checkbox_to_products() {
woocommerce_wp_checkbox(array(
'id' => 'custom_badge',
'class' => '',
'label' => 'Echt SPECHTWERK'
)
);
}
/* 2. Save checkbox via custom field */
add_action('save_post', 'bbloomer_save_badge_checkbox_to_post_meta');
function bbloomer_save_badge_checkbox_to_post_meta($product_id) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
return;
if (isset($_POST['custom_badge'])) {
update_post_meta($product_id, 'custom_badge', $_POST['custom_badge']);
} else
delete_post_meta($product_id, 'custom_badge');
}
// 3. Display badge # single product page if checkbox checked
add_action('woocommerce_single_product_summary', 'bbloomer_display_badge_if_checkbox', 6);
function bbloomer_display_badge_if_checkbox() {
global $product;
if (get_post_meta($product->get_id(), 'custom_badge', true)) {
?> <div class="echt-spechtwerk-badge">
<img class="advantages-symbols" src="<?php echo get_bloginfo('wpurl') . '/wp-content/uploads/echt-SPECHTWERK-V6.svg' ?>">
</div>
<?php
}
}
Add the follows code for product bulk edit and quick edit with custom field -
function add_custom_field_in_bulk_edit_quick_edit(){
echo '<div class="inline-edit-group">';
woocommerce_wp_checkbox( array(
'id' => 'custom_badge',
'class' => '',
'label' => 'Echt SPECHTWERK'
) );
echo '</div>';
}
add_action( 'woocommerce_product_quick_edit_end', 'add_custom_field_in_bulk_edit_quick_edit', 99 );
add_action( 'woocommerce_product_bulk_edit_end', 'add_custom_field_in_bulk_edit_quick_edit', 99 );
function save_custom_field_in_bulk_edit_quick_edit( $post_id, $post ){
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
if ( 'product' !== $post->post_type ) return $post_id;
if (isset($_REQUEST['custom_badge'])) {
update_post_meta( $post_id, 'custom_badge', $_REQUEST['custom_badge'] );
} else {
delete_post_meta( $post_id, 'custom_badge' );
}
}
add_action( 'woocommerce_product_bulk_and_quick_edit', 'save_custom_field_in_bulk_edit_quick_edit', 99, 2 );

Make Order notes field required only when it is not hidden in Woocommerce checkout

In Woocommerce checkout page, I have managed to show or hide "Order notes" field when "ship-to-different-address" checkbox is checked or unchecked, using "Show hide Order notes field based on a checkbox in Woocommerce checkout" answer code to one of my questions.
I would like "Order notes" field to be required only when it's visible.
How can I make this "Order notes" field required when it's visible (not hidden) and enable the validation for it?
Any help is welcome.
The following code will make "Order notes" field to be required only when it's not hidden and will enable in this case the field validation.
Note (mandatory): The "Order notes" field has to be optional (just as in default Woocommerce), without that the code will not work properly.
The complete code:
// Remove "(optional)" label on "Order notes" field
add_filter( 'woocommerce_form_field' , 'remove_order_comments_optional_fields_label', 10, 4 );
function remove_order_comments_optional_fields_label( $field, $key, $args, $value ) {
// Only on checkout page for Order notes field
if( 'order_comments' === $key && is_checkout() ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// The jQuery script that show hide "Order notes" field
add_action( 'woocommerce_after_order_notes', 'custom_checkout_scripts_js_script', 10, 1 );
function custom_checkout_scripts_js_script( $checkout ) {
$required = esc_html__( 'required', 'woocommerce' );
?>
<script type="text/javascript">
(function($){
var required = '<abbr class="required" title="<?php echo $required; ?>">*</abbr>',
notesField = '#order_comments_field',
shipCheckbox = '#ship-to-different-address-checkbox';
function actionRequire( actionToDo='yes', selector='' ){
if ( actionToDo == 'yes' ) {
$(selector).addClass("validate-required");
$(selector+' label').append(required);
} else {
$(selector).removeClass("validate-required");
$(selector+' label > .required').remove();
}
$(selector).removeClass("woocommerce-validated");
$(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
}
// On load and on form change
$('form.checkout').on( 'change', shipCheckbox, function(){
if( $(this).prop('checked') === true ) {
$(notesField).hide(); // Show
actionRequire( 'no' ,notesField );
} else {
$(notesField).show(); // Hide
actionRequire( 'yes' ,notesField );
}
});
})(jQuery);
</script>
<?php
}
// "Order notes" field validation
add_action('woocommerce_checkout_process', 'order_comments_field_validation');
function order_comments_field_validation() {
if ( isset($_POST['order_comments']) && empty($_POST['ship_to_different_address']) )
wc_add_notice( __( 'Please fill in "Order notes" required field.' ), 'error' );
}
Code goes on function.php file of your active child theme (or active theme). Tested and works.
Similar: Make Woocommerce checkout phone field optional based on shipping country
Related: Show hide Order notes field based on a checkbox in Woocommerce checkout

Categories