I want country dropdown on woocommerce as readonly.
I already set the default country to australia but I want them to be readonly.
The answer of Kashalo is correct… You can also use one of this multiple other ways:
1) For Checkout Billing country only:
add_filter('woocommerce_checkout_fields', 'readdonly_billing_country_select_field');
function readdonly_billing_country_select_field( $fields ) {
// Set billing and shipping country to AU
WC()->customer->set_billing_country('AU');
// Make billing country field read only
$fields['billing']['billing_country']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
2) For Checkout and My account Billing country only:
add_filter('woocommerce_billing_fields', 'readdonly_billing_country_select_field');
function readdonly_billing_country_select_field( $fields ) {
// Set billing and shipping country to AU
WC()->customer->set_billing_country('AU');
// Make billing country field read only
$fields['billing_country']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
3 For Checkout billing and shipping country:
add_filter('woocommerce_checkout_fields', 'readdonly_country_select_field');
function readdonly_country_select_field( $fields ) {
// Set billing and shipping country to AU
WC()->customer->set_billing_country('AU');
WC()->customer->set_shipping_country('AU');
// Make billing and shipping country field read only
$fields['billing']['billing_country']['custom_attributes'] = array( 'disabled' => 'disabled' );
$fields['shipping']['shipping_country']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
4) For Checkout and My account billing and shipping country:
add_filter('woocommerce_default_address_fields', 'readdonly_country_select_field');
function readdonly_country_select_field( $fields ) {
// Set billing and shipping country to AU
WC()->customer->set_billing_country('AU');
WC()->customer->set_shipping_country('AU');
// Make country field read only
$fields['country']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
you can use woocommerce_form_field_args to add disabled attribute to the quntry select field.
add the following code to your functions.php and you will get the desired result.
add_action('woocommerce_form_field_args', 'disable_country_dropdown', 10, 3);
function disable_country_dropdown($args, $key, $value)
{
if ($key == 'billing_country') {
$args['custom_attributes'] = [
'disabled' => 'disabled',
];
}
return $args;
}
the issue when we puted the select drowpdown disabled the option value is not passed when you click place order and in order to solve this issue we can add hidden field with our desired value as follow:
add_action('woocommerce_after_order_notes', 'billing_country_hidden_field');
function billing_country_hidden_field($checkout)
{
echo '<input type="hidden" class="input-hidden" name="billing_country" value="PL">';
}
just change the value="PL" to your country code value and everything will work as expected.
OutPut :
Code is tested with StorrFront Theme.
/*CHECKOUT BILLING ADDRESS READ ONLY*/
add_action('woocommerce_checkout_fields','customization_readonly_billing_fields',10,1);
function customization_readonly_billing_fields($checkout_fields){
$current_user = wp_get_current_user();;
$user_id = $current_user->ID;
foreach ( $checkout_fields['billing'] as $key => $field ){
if($key == 'billing_company' || $key == 'billing_address_1' || $key == 'billing_address_2' || $key == 'billing_city' || $key == 'billing_postcode' || $key == 'billing_phone' || $key == 'invoice_email' || $key == 'purchase_order' || $key == 'ship_to_first_name' || $key == 'ship_to_last_name'){
$key_value = get_user_meta($user_id, $key, true);
if( strlen($key_value)>0){
$checkout_fields['billing'][$key]['custom_attributes'] = array('readonly'=>'readonly');
}
}
}
return $checkout_fields;
}
if ( is_user_logged_in() ) {
// your code for logged in user
add_filter('woocommerce_checkout_fields', 'readdonly_billing_country_select_field');
function readdonly_billing_country_select_field( $fields ) {
$fields['billing']['billing_country']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
add_filter('woocommerce_checkout_fields', 'readdonly_billing_state_select_field');
function readdonly_billing_state_select_field( $fields ) {
$fields['billing']['billing_state']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
} else {
// your code for logged out user
}
Related
Need to add a field to the WooCommerce order details page where I can add a tracking number in the order page to be displayed for the customer.
I have added ACF to the order-details.php template as below, but it does not display. When I inspect page element all I can see is <h2></h2>. This is my current ACF code:
<h2><?php the_field('tracking_number'); ?></h2>
You can use the following to dis
// Display tracking information as a row on order totals everywhere
add_filter( 'woocommerce_get_order_item_totals', 'order_item_totals_tracking_row', 1000, 3 );
function order_item_totals_tracking_row( $total_rows, $order, $tax_display ){
if( $tracking_number = get_field('tracking_number', $order->get_id()) ) {
$new_total_rows = []; // Initializing
$has_tracking_row = false; // Initializing
$tracking_row = array( // tracking information array
'label' => __("Tracking number", "woocommerce"),
'value' => $tracking_number
);
// Loop through order total rows
foreach( $total_rows as $key => $values ) {
$new_total_rows[$key] = $values;
// Inserting tracking information array
if( $key === 'shipping' ) {
$new_total_rows['tracking'] = $tracking_row;
$has_tracking_row = true;
} elseif( $key === 'payment_method' && ! $has_tracking_row ) {
$new_total_rows['tracking'] = $tracking_row;
}
}
return $new_total_rows;
}
return $total_rows;
}
Code goes in functions.php file of the active child theme (or active theme). It should works.
I would like to prevent (make these fields readonly, for example) users from changing their billing information on the WooCommerce checkout form.
I'm currently using this code snippet:
add_filter('woocommerce_billing_fields', 'mycustom_woocommerce_billing_fields', 10, 1 );
function mycustom_woocommerce_billing_fields($fields)
{
$fields['billing_first_name']['custom_attributes'] = array('readonly'=>'readonly');
$fields['billing_last_name']['custom_attributes'] = array('readonly'=>'readonly');
$fields['billing_email']['custom_attributes'] = array('readonly'=>'readonly');
$fields['billing_phone']['custom_attributes'] = array('readonly'=>'readonly');
return $fields;
}
But the problem is: If the user has not filled in any of these fields in the registration, he is unable to insert his data in the checkout form because these fields are not editable.
My question is:
If the fields are not empty, how to make them readonly (or disabled)
Someone who can help me with this?
The answer of 7uc1f3r certainly works getting the user data… But since WooCommerce 3, you can use WC_Checkout get_value() dedicated method as follow:
add_filter( 'woocommerce_billing_fields', 'filter_wc_billing_fields', 10, 1 );
function filter_wc_billing_fields( $fields ) {
// On checkout and if user is logged in
if ( is_checkout() && is_user_logged_in() ) {
// Define your key fields below
$keys_fields = ['billing_first_name', 'billing_last_name', 'billing_email', 'billing_phone'];
// Loop through your specific defined fields
foreach ( $keys_fields as $key ) {
// Check that a value exist for the current field
if( ( $value = WC()->checkout->get_value($key) ) && ! empty( $value ) ) {
// Make it readonly if a value exist
$fields[$key]['custom_attributes'] = ['readonly'=>'readonly'];
}
}
}
return $fields;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
If you want this code to be also active in My account > Addresses > edit…, you will just have to remove is_checkout() && from the first IF statement.
I believe this is what you are looking for, comment with explanation added in code
function mycustom_woocommerce_billing_fields( $fields ) {
// Get current user
$user = wp_get_current_user();
// User id
$user_id = $user->ID;
// User id is found
if ( $user_id > 0 ) {
// Fields
$read_only_fields = array ( 'billing_first_name', 'billing_last_name', 'billing_email', 'billing_phone' );
// Loop
foreach ( $fields as $key => $field ) {
if( in_array( $key, $read_only_fields ) ) {
// Get key value
$key_value = get_user_meta($user_id, $key, true);
if( strlen( $key_value ) > 0 ) {
$fields[$key]['custom_attributes'] = array(
'readonly'=>'readonly'
);
}
}
}
}
return $fields;
}
add_filter('woocommerce_billing_fields', 'mycustom_woocommerce_billing_fields', 10, 1 );
With the code below, I am able to change the display of specific shipping methods full labels on WooCommerce cart and checkout pages:
add_filter( 'woocommerce_cart_shipping_method_full_label', 'custom_shipping_labels', 10000, 2 );
function custom_shipping_labels($label, $method){
$shpmethod = $label;
if(strpos($shpmethod, 'Express Shipping') !== false){
$shpmethod = str_replace('Express Shipping',' test express lbl',$shpmethod);
}
elseif(strpos($shpmethod, 'Free Standard Shipping') !== false){
$shpmethod = str_replace('Free Standard Shipping',' test free lbl',$shpmethod);
}
return $shpmethod;
}
Now I need to access the customer selected county inside that custom function hooked in woocommerce_cart_shipping_method_full_label filter hook.
Is it possible to get the customer selected country in that hooked function?
To get the selected shipping country you can use one of those:
from WC_Session data WC()->session->get('customer')['shipping_country'].
or WC()->checkout->get_value('shipping_country')
or from WC_Customer data: WC()->customer->get_shipping_country().
For testing purpose, here with the code below, selected (or customer) billing country code is displayed with each shipping method full label:
add_filter( 'woocommerce_cart_shipping_method_full_label', 'custom_shipping_labels', 10000, 2 );
function custom_shipping_labels($label, $method){
// Get selected shipping country value (country code)
$shipping_country = WC()->checkout->get_value('shipping_country');
// If shipping country is empty, we get it from customer data
if( empty( $shipping_country ) ) {
$shipping_country = WC()->customer->get_shipping_country();
}
return $label .' ('.$shipping_country. ')';
}
Now in your code you can use $method->label to target each defined shipping method label string, which is more efficient. So your code will be:
add_filter( 'woocommerce_cart_shipping_method_full_label', 'custom_shipping_labels', 10000, 2 );
function custom_shipping_labels($label, $method){
// Get selected checkout shipping country value (country code)
$shipping_country = WC()->checkout->get_value('shipping_country');
// If shipping country is empty, we get it from customer data
if( empty( $shipping_country ) ) {
$shipping_country = WC()->customer->get_shipping_country();
}
if ( $method->label == 'Express Shipping' ) {
$label = str_replace( $method->label, __('test express lbl'), $label );
}
elseif ( $method->label == 'Free Standard Shipping' ) {
$label = str_replace( $method->label, __('test free lbl'), $label );
}
return $label;
}
Code goes in functions.php file of your active child theme (active theme). Tested and works.
Now you can use the selected shipping country as you wish.
For that you can use WC_Customer::get_shipping_country()
https://docs.woocommerce.com/wc-apidocs/class-WC_Customer.html
function custom_shipping_labels( $label, $method ) {
// DEBUG
//echo '<pre>', print_r($label, 1), '</pre>';
//echo '<pre>', print_r($method, 1), '</pre>';
// Get shipping country
$shipping_country = WC()->customer->get_shipping_country();
// DEBUG
echo $shipping_country . '<br>';
if ( $shipping_country == 'BE' ) {
echo 'Yeey' . '<br>';
}
if( strpos( $label, 'Express Shipping') !== false) {
$label = str_replace( 'Express Shipping',' test express lbl', $label );
} elseif( strpos( $label, 'Free Standard Shipping') !== false) {
$label = str_replace( 'Free Standard Shipping',' test free lbl', $label );
}
return $label;
}
add_filter( 'woocommerce_cart_shipping_method_full_label', 'custom_shipping_labels', 10, 2 );
In Woocommerce checkout, I am trying to make the phone field not required for specific shipping countries. Based on "Make checkout phone field optional for specific countries in WooCommerce" answer code, which works fine, I have tried to make some changes to get this code working for the shipping country rather than billing country.
After a lot of tries, I wasn't able to figure out how to make it work.
Any help will be awesome and greatly appreciated.
The following code will make billing phone field required only for specific "Shipping" countries.
Since Woocommerce version 3.4+, things have changed a bit on Woocommerce form fields, so additional functions and code where required.
Also I have extended the code to handle the phone field behavior in My Account > Edit Addresses, where customer can make changes to his account data.
Here is the complete code (define your country codes in the first function):
// SETTINGS: The countries codes (2 capital letters) in the array
function defined_countries_for_phone_field(){
return array( 'UK', 'BE', 'GE', 'IT', 'ES' );
}
// Remove "(optional)" from non required "Billing phone" field
add_filter( 'woocommerce_form_field' , 'remove_checkout_optional_fields_label', 10, 4 );
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) {
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Get Customer shipping country
$shipping_country = WC()->customer->get_shipping_country();
// Only on checkout page and My account > Edit address for billing phone field
if( 'billing_phone' === $key && ( ( is_wc_endpoint_url( 'edit-address' )
&& ! in_array($shipping_country, $countries) ) || is_checkout() ) ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// Make the billing phone field optional (by default)
add_filter( 'woocommerce_billing_fields', 'filter_billing_phone_field', 10, 1 );
function filter_billing_phone_field( $fields ) {
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Get Customer shipping country
$shipping_country = WC()->customer->get_shipping_country();
// Only on checkout page and My account > Edit address
if ( ( is_wc_endpoint_url( 'edit-address' )
&& ! in_array($shipping_country, $countries) ) || is_checkout() )
$fields['billing_phone']['required'] = false;
return $fields;
}
// Real time shipping country selection actions
add_action( 'woocommerce_after_order_notes', 'custom_checkout_scripts_and_fields', 10, 1 );
function custom_checkout_scripts_and_fields( $checkout ) {
$required = esc_attr__( 'required', 'woocommerce' );
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Hidden field for the phone number validation
echo '<input type="hidden" name="billing_phone_check" id="billing_phone_check" value="0">';
$countries_str = "'".implode( "', '", $countries )."'"; // Formatting countries for jQuery
?>
<script type="text/javascript">
(function($){
var required = '<abbr class="required" title="<?php echo $required; ?>">*</abbr>',
countries = [<?php echo $countries_str; ?>],
location = $('#shipping_country option:selected').val(),
phoneCheck = 'input#billing_phone_check',
phoneField = '#billing_phone_field';
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");
}
// Default value Once DOM is loaded (with a 300 ms delay)
setTimeout( function(){
actionRequire( 'no', phoneField );
if( $.inArray( location, countries ) >= 0 && $(phoneCheck).val() == '0' ){
actionRequire( 'yes',phoneField );
$(phoneCheck).val('1');
}
}, 300 );
// Live value
$( 'form.checkout' ).on( 'change', '#shipping_country', function(){
var location = $('#shipping_country option:selected').val();
if ( $.inArray( location, countries ) >= 0 && $(phoneCheck).val() == 0 ) {
actionRequire( 'yes' ,phoneField );
$(phoneCheck).val('1');
} else if ( $(phoneCheck).val() == 1 ) {
actionRequire( 'no' ,phoneField );
$(phoneCheck).val('0');
}
});
})(jQuery);
</script>
<?php
}
// Phone number validation, when the field is required
add_action('woocommerce_checkout_process', 'billing_phone_field_process');
function billing_phone_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['billing_phone'] && $_POST['billing_phone_check'] == '1' )
wc_add_notice( __( 'Please enter a number phone.' ), 'error' );
}
Code goes in function.php file of your active child theme (or active theme). Tested and works in WooCommerce from version 3.4 and above.
Related:
Make checkout phone field optional for specific countries in WooCommerce
Remove "(optional)" text from checkout fields in Woocommerce 3.4+
Huge thanks to #LoicTheAztec for the original answer, however the solution now gives erratic results and just alternately switches the phone field between required and optional states (on / off).
The original answer also does not take into account customers who are using the billing address only and have not entered a separate delivery or shipping address.
Please see the updated version below for 2019
// SETTINGS: The countries codes (2 capital letters) in the array
function defined_countries_for_phone_field(){
return array( 'GB', 'JE', 'GG', 'IM' );
}
// Remove "(optional)" from non required "Billing phone" field
add_filter( 'woocommerce_form_field' , 'remove_checkout_optional_fields_label', 10, 4 );
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) {
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Get Customer shipping country
$shipping_country = WC()->customer->get_shipping_country();
// Only on checkout page and My account > Edit address for billing phone field
if( 'billing_phone' === $key && ( ( is_wc_endpoint_url( 'edit-address' )
&& in_array($shipping_country, $countries) ) || is_checkout() ) ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// Make the billing phone field optional (by default)
add_filter( 'woocommerce_billing_fields', 'filter_billing_phone_field', 10, 1 );
function filter_billing_phone_field( $fields ) {
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Get Customer shipping country
$shipping_country = WC()->customer->get_shipping_country();
// Only on checkout page and My account > Edit address
if ( ( is_wc_endpoint_url( 'edit-address' )
&& in_array($shipping_country, $countries) ) || is_checkout() )
$fields['billing_phone']['required'] = false;
return $fields;
}
// Real time shipping country selection actions
add_action( 'woocommerce_after_order_notes', 'custom_checkout_scripts_and_fields', 10, 1 );
function custom_checkout_scripts_and_fields( $checkout ) {
$required = esc_attr__( 'required', 'woocommerce' );
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Hidden field for the phone number validation
echo '<input type="hidden" name="billing_phone_check" id="billing_phone_check" value="0">';
$countries_str = "'".implode( "', '", $countries )."'"; // Formatting countries for jQuery
?>
<script type="text/javascript">
(function($){
var required = '<abbr class="required" title="<?php echo $required; ?>">*</abbr>';
var countries = [<?php echo $countries_str; ?>];
if($('.shipping_address').is(':visible')) {
// ship to different country selected
var selectedcountry = $('#shipping_country option:selected').val();
} else {
var selectedcountry = $('#billing_country option:selected').val();
}
//var selectedcountry = $('#shipping_country option:selected').val();
var phoneCheck = 'input#billing_phone_check';
var phoneField = '#billing_phone_field';
function actionRequire( actionToDo='yes', selector='' ){
if ( actionToDo == 'yes' ) {
$(selector).addClass("validate-required");
$(selector+' label > .required').remove();
$(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");
}
// Default value Once DOM is loaded (with a 300 ms delay)
setTimeout( function(){
if($('.shipping_address').is(':visible')) {
// ship to different country selected
var selectedcountry = $('#shipping_country option:selected').val();
} else {
var selectedcountry = $('#billing_country option:selected').val();
}
actionRequire( 'no', phoneField );
if( $.inArray( selectedcountry, countries ) == -1){
actionRequire( 'yes',phoneField );
$(phoneCheck).val('1');
}
}, 300 );
// Live value
$( 'form.checkout' ).on( 'change', '#billing_country, #shipping_country, #ship-to-different-address-checkbox', function(){
setTimeout( function(){
if($('.shipping_address').is(':visible')) {
// ship to different country selected
var selectedcountry = $('#shipping_country option:selected').val();
} else {
var selectedcountry = $('#billing_country option:selected').val();
}
if ( $.inArray( selectedcountry, countries ) == -1) {
actionRequire( 'yes' ,phoneField );
$(phoneCheck).val('1');
} else {
actionRequire( 'no' ,phoneField );
$(phoneCheck).val('0');
}
}, 300 );
});
})(jQuery);
</script>
<?php
}
// Phone number validation, when the field is required
add_action('woocommerce_checkout_process', 'billing_phone_field_process');
function billing_phone_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['billing_phone'] && $_POST['billing_phone_check'] == '1' )
wc_add_notice( __( 'Please enter a number phone.' ), 'error' );
}
Could someone tell me what am I doing wrong with this Ninja Forms hook:
add_filter( 'ninja_forms_submit_data', 'my_ninja_forms_submit_data' );
function my_ninja_forms_submit_data( $form_data ) {
foreach( $form_data[ 'fields' ] as $field ) {
if( 'test_page_url_1519171605789' == $field['key'] ){
$current_url = "my url - {$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
$field[ 'value' ] = $current_url;
}
}
$form_settings = $form_data[ 'settings' ]; // Form settings.
$extra_data = $form_data[ 'extra' ]; // Extra data included with the submission.
return $form_data;
}
I am trying to modify the hidden form field with the key value "test_page_url_1519171605789" so that it contains a URL.
I was able to solve this issue by using this code instead:
add_filter( 'ninja_forms_submit_data', 'my_ninja_forms_submit_data' );
function my_ninja_forms_submit_data( $form_data ) {
//Need to set the current URL as the previous page since
//REQUEST_URI was returning /wp-admin/admin-ajax.php
//instead of the form's actual URL.
$current_url = $_SERVER['HTTP_REFERER'];
foreach( $form_data[ 'fields' ] as $key => $field ) {
//I need to look for the field ID and not the field key
if( $key == '197' || $key == '195' || $key == '196' || $key == '179' ){
// Update the submitted field value with the URL to the previous page.
$form_data['fields'][$key]['value'] = $current_url;
}
}
// Form settings.
$form_settings = $form_data[ 'settings' ];
// Extra data included with the submission.
$extra_data = $form_data[ 'extra' ];
return $form_data;
}