Reputation: 386
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:
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;
}
Upvotes: 2
Views: 893
Reputation: 191
there are a fair few issues with that code
namely Warning: Undefined array key "account_password" in /var/www/html/wp-content/themes/storefront/functions.php
but here is the solution to your initial problem
// 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($) {
// re-usable function to play around with the checkout fields if needed in the
// future
const toggleElmVisibility = (selector = '', show = true, duration = 200) => {
if (show) {
$(selector).show(duration);
return;
}
$(selector).hide(duration);
}
// hide password fields on page load, unless they have alredy checked the checkbox
toggleElmVisibility('#account_password_field', $('#account_cb').is(':checked'));
$('#account_cb').on('change', function() {
toggleElmVisibility('#account_password_field', $(this).is(':checked'));
});
$('input[name=account_cb]').on('click', function() {
$('input[name=createaccount]').trigger('click');
});
})(jQuery);
</script>
<?php
endif;
}
Edit:
Changes to function to add the password field
// Move Account password field into billing section
function move_password_field( $checkout_fields ) {
//bail if not logged in
if ( is_user_logged_in() ) {
return $checkout_fields;
}
// Move Account Password into Billing if not logged in
$checkout_fields['billing']['account_password'] = $checkout_fields['account']['account_password'];
$checkout_fields['billing']['account_password'] = array(
'label' => __( 'Password', 'woocommerce' ), // Add custom field label
'placeholder' => _x( 'Password', 'placeholder', 'woocommerce' ), // Add custom field placeholder
'clear' => false, // add clear or not
'type' => 'text', // add field type
);
unset( $checkout_fields['account']['account_password'] );
return $checkout_fields;
} add_filter( 'woocommerce_checkout_fields', 'move_password_field', 999 );
change the remove optional text function to catch the new field
// remove "(optional)" from the new checkbox
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) {
// Only on checkout page
if ( is_checkout() && ! is_wc_endpoint_url() && ( $key === 'account_cb' || 'account_password' === $key ) ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
} add_filter( 'woocommerce_form_field', 'remove_checkout_optional_fields_label', 10, 4 );
submit validation
/**
* Validate the password field if checkbox is checked on checkout submit
*
* @return void
* @see https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/
*/
function woocomerce_validate_pass(): void {
if ( isset( $_POST['account_cb'] ) && empty( $_POST['account_password'] ) ) {
wc_add_notice( __( 'Please enter a password.', 'woocommerce' ), 'error' );
}
} add_action( 'woocommerce_after_checkout_validation', 'woocomerce_validate_pass' );
and changes to js to pickup that the field is required
(function($) {
// re-usable function to play around with the checkout fields if needed in the
const toggleElmVisibility = (selector = '', show = true, duration = 200) => {
if (show) {
$(selector).show(duration, () => {
$(selector).addClass("validate-required");
});
} else {
$(selector).hide(duration, () => {
$(selector).removeClass("validate-required");
});
}
$(selector).removeClass("woocommerce-validated");
$(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
}
// hide password fields on page load, unless they have alredy checked the checkbox
toggleElmVisibility('#account_password_field', $('#account_cb').is(':checked'));
$('#account_cb').on('change', function() {
toggleElmVisibility('#account_password_field', $(this).is(':checked'));
});
$('input[name=account_cb]').on('click', function() {
$('input[name=createaccount]').trigger('click');
});
})(jQuery);
the other functions have been removed, the complete code:
// Move Account password field into billing section
function move_password_field( $checkout_fields ) {
//bail if not logged in
if ( is_user_logged_in() ) {
return $checkout_fields;
}
// Move Account Password into Billing if not logged in
$checkout_fields['billing']['account_password'] = $checkout_fields['account']['account_password'];
$checkout_fields['billing']['account_password'] = array(
'label' => __( 'Password', 'woocommerce' ), // Add custom field label
'placeholder' => _x( 'Password', 'placeholder', 'woocommerce' ), // Add custom field placeholder
'clear' => false, // add clear or not
'type' => 'text', // add field type
);
unset( $checkout_fields['account']['account_password'] );
return $checkout_fields;
} add_filter( 'woocommerce_checkout_fields', 'move_password_field', 999 );
// Add a checkbox to billing section
function move_checkout_create_an_account_checkbox( $fields ) {
if ( is_user_logged_in() ) {
return $fields;
}
// 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' ),
'placeholder' => _x( 'Create an account?', 'placeholder', 'woocommerce' ),
'class' => array( 'form-row-wide' ),
);
return $fields;
} add_filter( 'woocommerce_checkout_fields', 'move_checkout_create_an_account_checkbox' );
// remove "(optional)" from the new checkbox
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) {
// Only on checkout page
if ( is_checkout() && ! is_wc_endpoint_url() && ( $key === 'account_cb' || 'account_password' === $key ) ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
} add_filter( 'woocommerce_form_field', 'remove_checkout_optional_fields_label', 10, 4 );
/**
* Validate the password field if checkbox is checked on checkout submit
*
* @return void
* @see https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/
*/
function woocomerce_validate_pass($fields, $errors): void {
if ( isset( $_POST['account_cb'] ) && empty( $_POST['account_password'] ) ) {
$errors->add( 'validation', 'Please enter a password.');
// wc_add_notice( __( 'Please enter a password.', 'woocommerce' ), 'error' );
}
} add_action( 'woocommerce_after_checkout_validation', 'woocomerce_validate_pass', 10, 2 );
// 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($) {
// re-usable function to play around with the checkout fields if needed in the
const toggleElmVisibility = (selector = '', show = true, duration = 200) => {
if (show) {
$(selector).show(duration, () => {
$(selector).addClass("validate-required");
});
} else {
$(selector).hide(duration, () => {
$(selector).removeClass("validate-required");
});
}
$(selector).removeClass("woocommerce-validated");
$(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
}
// hide password fields on page load, unless they have alredy checked the checkbox
toggleElmVisibility('#account_password_field', $('#account_cb').is(':checked'));
$('#account_cb').on('change', function() {
toggleElmVisibility('#account_password_field', $(this).is(':checked'));
});
$('input[name=account_cb]').on('click', function() {
$('input[name=createaccount]').trigger('click');
});
})(jQuery);
</script>
<?php
endif;
}
Upvotes: 3