I need to add three checkout fields in WooCommerce checkout:
A checkbox labelled "I'm already a member". Checking this will display a field below the checkbox where the person must fill in their member number, which is a 6 digit number. When the member number is filled in correctly, a discount of SEK 200,00 should be applied to every product in the checkout and the checkout amount should automatically be recalculated. The member number field must be required/mandatory when this box is checked.
A checkbox labelled "I'm a member, but in another club". Checking this will display a field below the checkbox where the person must fill in their member number, which is a 6 digit number. The member number field must be required/mandatory when this box is checked.
It must be required/mandatory to choose one of those two options, it shouldn't be possible to place the order without having checked one of the boxes, having filled their member number. It should not be possible to choose both boxes, only one of them is allowed. If a person checks box1 and then box2, box1 automatically should be unchecked and the discount should be removed.
For example, 3 products ordered, both box1 and box 3 are checked (and valid member number is filled in), the total discount will SEK 700,00. If 3 products are ordered, both box2 and box 3 are checked, the total discount will be SEK 100,00. If only box1 is checked, the total discount will be SEK 600,00.
I use the Astra theme and have access to the functions.php file.
I have added this to the functions.php. The SEK 100,00 is working, the other two don't work, no discount is applied.
add_action('woocommerce_review_order_before_submit', 'custom_checkout_fields');
function custom_checkout_fields() {
echo '<div class="woocommerce-additional-fields">';
// Kryssruta 1: Jag är medlem i klubben
woocommerce_form_field('is_member_checkbox', array(
'type' => 'checkbox',
'class' => array('input-checkbox'),
'label' => __('Jag är medlem i klubben'),
), WC()->session->get('is_member_checkbox'));
echo '<div class="is-member-fields" style="display:none;">';
woocommerce_form_field('member_number', array(
'type' => 'text',
'class' => array('input-text'),
'label' => __('Medlemsnummer'),
'placeholder' => __('Fyll i ditt medlemsnummer'),
), WC()->session->get('member_number'));
echo '</div>';
// Kryssruta 2: Jag har hjälpt till ideellt i klubben
woocommerce_form_field('volunteer_checkbox', array(
'type' => 'checkbox',
'class' => array('input-checkbox'),
'label' => __('Jag har hjälpt till ideellt i klubben'),
), WC()->session->get('volunteer_checkbox'));
// Kryssruta 3: Jag är medlem i annan klubb
woocommerce_form_field('other_club_checkbox', array(
'type' => 'checkbox',
'class' => array('input-checkbox'),
'label' => __('Jag är medlem i annan klubb'),
), WC()->session->get('other_club_checkbox'));
echo '<div class="other-club-fields" style="display:none;">';
woocommerce_form_field('other_club_number', array(
'type' => 'text',
'class' => array('input-text'),
'label' => __('Medlemsnummer i annan klubb'),
'placeholder' => __('Fyll i ditt medlemsnummer'),
), WC()->session->get('other_club_number'));
echo '</div>';
echo '</div>';
// JavaScript för att visa/dölja anpassade fält baserat på kryssrutor
?>
<script>
jQuery(document).ready(function($) {
$('#is_member_checkbox').change(function() {
if ($(this).is(':checked')) {
$('.is-member-fields').show();
} else {
$('.is-member-fields').hide();
}
recalculateCart();
});
$('#volunteer_checkbox').change(function() {
recalculateCart();
});
$('#other_club_checkbox').change(function() {
if ($(this).is(':checked')) {
$('.other-club-fields').show();
} else {
$('.other-club-fields').hide();
}
recalculateCart();
});
function recalculateCart() {
$('body').trigger('update_checkout');
}
});
</script>
<?php
}
// Applicera rabatt baserat på medlemsstatus
add_action('woocommerce_cart_calculate_fees', 'custom_apply_discounts');
function custom_apply_discounts($cart) {
if (is_admin() && !defined('DOING_AJAX'))
return;
if (isset($_POST['post_data'])) {
parse_str($_POST['post_data'], $post_data);
} else {
$post_data = $_POST;
}
if (isset($post_data['is_member_checkbox']) && $post_data['is_member_checkbox'] === '1' && !empty($post_data['member_number']) && preg_match('/^\d{6}$/', $post_data['member_number'])) {
$discount_amount = 200;
$cart->add_fee(__('Medlemsrabatt'), -$discount_amount, false);
WC()->session->set('is_member_checkbox', true);
WC()->session->set('member_number', $post_data['member_number']);
} else {
WC()->session->set('is_member_checkbox', false);
WC()->session->set('member_number', '');
}
if (isset($post_data['volunteer_checkbox']) && $post_data['volunteer_checkbox'] === '1') {
$volunteer_discount = 80; // Uppdatera rabattbeloppet här
$cart->add_fee(__('Ideell rabatt'), -$volunteer_discount, false);
WC()->session->set('volunteer_checkbox', true);
} else {
WC()->session->set('volunteer_checkbox', false);
}
if (isset($post_data['other_club_checkbox']) && $post_data['other_club_checkbox'] === '1' && !empty($post_data['other_club_number']) && preg_match('/^\d{6}$/', $post_data['other_club_number'])) {
foreach ($cart->get_fees() as $fee_key => $fee) {
if ($fee->get_name() === 'Medlemsrabatt') {
$cart->remove_fee($fee_key);
break;
}
}
WC()->session->set('other_club_checkbox', true);
WC()->session->set('other_club_number', $post_data['other_club_number']);
} else {
WC()->session->set('other_club_checkbox', false);
WC()->session->set('other_club_number', '');
}
}
// Återställ kryssrutor vid sidan uppdateras
add_action('woocommerce_before_checkout_form', 'custom_reset_session');
function custom_reset_session() {
if (is_checkout() && WC()->session->get('order_awaiting_payment') !== '1') {
WC()->session->set('is_member_checkbox', false);
WC()->session->set('volunteer_checkbox', false);
WC()->session->set('other_club_checkbox', false);
WC()->session->set('member_number', '');
WC()->session->set('other_club_number', '');
}
}
// Validera Nonce för att undvika nonce_failure
add_action('woocommerce_after_checkout_validation', 'custom_validate_nonce');
function custom_validate_nonce($posted_data) {
if (isset($posted_data['is_member_checkbox']) && $posted_data['is_member_checkbox'] === '1') {
if (!isset($posted_data['is_member_checkbox_nonce']) || !wp_verify_nonce($posted_data['is_member_checkbox_nonce'], 'is_member_checkbox_action')) {
wc_add_notice(__('Ogiltig förfrågan. Vänligen uppdatera sidan och försök igen.'), 'error');
}
}
if (isset($posted_data['other_club_checkbox']) && $posted_data['other_club_checkbox'] === '1') {
if (!isset($posted_data['other_club_checkbox_nonce']) || !wp_verify_nonce($posted_data['other_club_checkbox_nonce'], 'other_club_checkbox_action')) {
wc_add_notice(__('Ogiltig förfrågan. Vänligen uppdatera sidan och försök igen.'), 'error');
}
}
}
There were some mistakes, errors and missing things in your code… So I have revisited your code everywhere, removing some unnecessary blocks, moved the JavaScript to its own function (queuing it to be output in the footer).
Both related discounts have now the correct behavior, and work as planed.
The checkout custom field validation is now working perfectly, just as you expect. Now customers will be obliged to choose one of your 2 mmandatory options, and to fill up correctly the related "member numbers".
When the cart is recalculated (when chosing an option), the related "member number" visible field is not hidden anymore.
// Custom checkput fields in review order before submit
add_action('woocommerce_review_order_before_submit', 'custom_checkout_fields');
function custom_checkout_fields() {
echo '<div class="woocommerce-additional-fields">';
// Kryssruta 1: Jag är medlem i klubben
woocommerce_form_field('is_member_checkbox', array(
'type' => 'checkbox',
'class' => array('input-checkbox'),
'label' => __('Jag är medlem i klubben'),
), WC()->session->get('is_member_checkbox') );
echo '<div class="is-member-fields" style="display:none;">';
woocommerce_form_field('member_number', array(
'type' => 'text',
'class' => array('input-text'),
'label' => __('Medlemsnummer'),
'placeholder' => __('Fyll i ditt medlemsnummer'),
'required' => true, // <== Required
), WC()->session->get('member_number') );
echo '</div>';
// Kryssruta 2: Jag har hjälpt till ideellt i klubben
woocommerce_form_field('volunteer_checkbox', array(
'type' => 'checkbox',
'class' => array('input-checkbox'),
'label' => __('Jag har hjälpt till ideellt i klubben'),
), WC()->session->get('volunteer_checkbox'));
// Kryssruta 3: Jag är medlem i annan klubb
woocommerce_form_field('other_club_checkbox', array(
'type' => 'checkbox',
'class' => array('input-checkbox'),
'label' => __('Jag är medlem i annan klubb'),
), WC()->session->get('other_club_checkbox'));
echo '<div class="other-club-fields" style="display:none;">';
woocommerce_form_field('other_club_number', array(
'type' => 'text',
'class' => array('input-text'),
'label' => __('Medlemsnummer i annan klubb'),
'placeholder' => __('Fyll i ditt medlemsnummer'),
'required' => true, // <== Required
), WC()->session->get('other_club_number'));
echo '</div>
</div>';
// (removed javascript to queue it after the footer)
}
// Remove "(optional)" from some non required fields
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() && ( 'is_member_checkbox' === $key || 'other_club_checkbox' === $key )) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// JavaScript för att visa/dölja anpassade fält baserat på kryssrutor
add_filter( 'woocommerce_after_checkout_form' , 'my_checkout_js_script' );
function my_checkout_js_script() {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
ob_start(); // Start buffering (instead of displaying)
?>
<script>
var isMemberCheckbox = false, isOtherClubCheckbox = false,
memberNumberVal = '', otherClubNumberVal = '',
memberNumberIsFilled = false, otherClubNumberIsFilled = false;
function recalculateCart() {
$('body').trigger('update_checkout');
}
// Checkout form delegated events
$('form.checkout').on( 'change', '#is_member_checkbox', function() {
if ($(this).is(':checked')) {
$('.is-member-fields').show();
isMemberCheckbox = true;
isOtherClubCheckbox = false;
if ($('#other_club_checkbox').is(':checked')) {
$('#other_club_checkbox').prop('checked', false); // uncheck checkbox
otherClubNumberVal = ''; // reset variable value
otherClubNumberIsFilled = false;
$('#other_club_number').val(otherClubNumberVal); // reset field value
$('.other-club-fields').hide(); // Hide fied
}
recalculateCart();
} else {
$('.is-member-fields').hide();
isMemberCheckbox = false;
memberNumberVal = ''; // reset variable value
memberNumberIsFilled = false;
$('#member_number').val(memberNumberVal); // reset the field value
recalculateCart();
}
}).on('mouseleave blur', '.is-member-fields', function() {
memberNumberVal = $('#member_number').val();
if ( ! memberNumberIsFilled && memberNumberVal != '' ) {
recalculateCart();
memberNumberIsFilled = true;
}
}).on( 'change', '#volunteer_checkbox', function() {
recalculateCart();
}).on( 'change', '#other_club_checkbox', function() {
if ($(this).is(':checked')) {
$('.other-club-fields').show();
isOtherClubCheckbox = true;
isMemberCheckbox = false;
if ($('#is_member_checkbox').is(':checked')) {
$('#is_member_checkbox').prop('checked', false); // uncheck checkbox
memberNumberVal = '';
memberNumberIsFilled = false
$('#member_number').val(memberNumberVal); // reset field value
$('.is-member-fields').hide();
}
recalculateCart();
} else {
$('.other-club-fields').hide();
isOtherClubCheckbox = false;
otherClubNumberVal = '';
otherClubNumberIsFilled = false;
$('#other_club_number').val(otherClubNumberVal); // reset the field value
recalculateCart();
}
}).on('mouseleave blur', '#other_club_number', function() {
otherClubNumberVal = $('#other_club_number').val();
if ( ! otherClubNumberIsFilled && otherClubNumberVal != '' ) {
recalculateCart();
otherClubNumberIsFilled = true;
}
});
// Document body delegated events
$('body').on( 'updated_checkout', function() {
if ( isMemberCheckbox ) {
if ( ! $('#is_member_checkbox').is(':checked') ) {
$('#is_member_checkbox').prop('checked', true);
}
$('.is-member-fields').show();
}
if ( isOtherClubCheckbox ) {
if ( ! $('#other_club_checkbox').is(':checked') ) {
$('#other_club_checkbox').prop('checked', true);
}
$('.other-club-fields').show();
}
}).on('update_checkout', function(){
// On "update" checkout form event Remove "(optional)" from some custom checkbox fields
$('#is_member_checkbox_field label > .optional').remove();
$('#other_club_checkbox_field label > .optional').remove();
});
</script>
<?php
$js_code = ob_get_clean(); // Set the buffered content in a variable
$js_code = str_replace( ['<script>', '</script>'], ['', ''], $js_code ); // Removing some html tags
wc_enqueue_js($js_code); // Queue this JavaScript code to be output in the footer
}
// Applicera rabatt baserat på medlemsstatus
add_action('woocommerce_cart_calculate_fees', 'custom_apply_discounts');
function custom_apply_discounts($cart) {
if (is_admin() && !defined('DOING_AJAX'))
return;
if (isset($_POST['post_data'])) {
parse_str($_POST['post_data'], $post_data);
} else {
$post_data = $_POST;
}
if (isset($post_data['is_member_checkbox']) && $post_data['is_member_checkbox'] === '1' && isset($post_data['member_number']) && preg_match('/^\d{6}$/', $post_data['member_number'])) {
$discount_by_item = 200; // Discount by item quantity
$number_of_items = $cart->get_cart_contents_count();
$discount_amount = $discount_by_item * $number_of_items;
$cart->add_fee(__('Medlemsrabatt'), -$discount_amount, false);
WC()->session->set('is_member_checkbox', true);
WC()->session->set('member_number', $post_data['member_number']);
} else {
WC()->session->set('is_member_checkbox', false);
WC()->session->set('member_number', '');
}
if (isset($post_data['volunteer_checkbox']) && $post_data['volunteer_checkbox'] === '1') {
$volunteer_discount = 80; // Uppdatera rabattbeloppet här
$cart->add_fee(__('Ideell rabatt'), -$volunteer_discount, false);
WC()->session->set('volunteer_checkbox', true);
} else {
WC()->session->set('volunteer_checkbox', false);
}
if (isset($post_data['other_club_checkbox']) && $post_data['other_club_checkbox'] === '1' && !empty($post_data['other_club_number']) && preg_match('/^\d{6}$/', $post_data['other_club_number'])) {
WC()->session->set('other_club_checkbox', true);
WC()->session->set('other_club_number', $post_data['other_club_number']);
} else {
WC()->session->set('other_club_checkbox', false);
WC()->session->set('other_club_number', '');
}
}
// Återställ kryssrutor vid sidan uppdateras
add_action('woocommerce_before_checkout_form', 'custom_reset_session');
function custom_reset_session() {
if (is_checkout() && WC()->session->get('order_awaiting_payment') !== '1') {
WC()->session->set('is_member_checkbox', false);
WC()->session->set('volunteer_checkbox', false);
WC()->session->set('other_club_checkbox', false);
WC()->session->set('member_number', '');
WC()->session->set('other_club_number', '');
}
}
// Custom checkout fields validation
add_action('woocommerce_checkout_process', 'custom_checkout_field_validation');
function custom_checkout_field_validation() {
$member_club_cb = isset($_POST['is_member_checkbox']) && $_POST['is_member_checkbox'] === '1';
$other_club_cb = isset($_POST['other_club_checkbox']) && $_POST['other_club_checkbox'] === '1';
if ( ! ( $member_club_cb || $other_club_cb ) ) {
wc_add_notice(__('Choose between "is_member_checkbox" or "other_club_checkbox" required options'), 'error');
}
if ( $member_club_cb && isset($_POST['member_number']) ) {
if ( $member_club_cb && isset($_POST['member_number']) && empty($_POST['member_number']) ) {
wc_add_notice( __('Please fill in the "Member number" field.'), 'error');
}
elseif ( 1 !== preg_match('/^\d{6}$/', $_POST['member_number']) ) {
wc_add_notice( __('Please fill in the "Member number" field with a correct number.'), 'error');
}
}
if ( $other_club_cb && isset($_POST['other_club_number']) ) {
if ( empty($_POST['other_club_number']) ) {
wc_add_notice( __('Please fill in the "Other Club number" field.'), 'error');
}
elseif ( 1 !== preg_match('/^\d{6}$/', $_POST['other_club_number']) ) {
wc_add_notice( __('Please fill in the "Other Club number" field with a correct number.'), 'error');
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.