Wordpress - radio button checkout woocommerce show/hide required field
Asked Answered
M

1

8

I'm Italian (sorry for my english) and I'm not a programmer.

I need to insert in my checkout woocommerce site, a radio button with two options to answer this question: "Sei un privato cittadino, un'azienda o un libero professionista?". These are the options: 1) Privato cittadino 2) Azienda o libero professionista

When users click on the first option, it has to show a required field: "codice fiscale". When users click on the second option, it has to show two required fields: "P.Iva" and "Ragione sociale". I've created the radio field with this code in form-billing.php:

    <div class="woocommerce-billing-fields">
    <?php if ( wc_ship_to_billing_address_only() && WC()->cart->needs_shipping() ) : ?>

        <h3><?php _e( 'Billing &amp; Shipping', 'woocommerce' ); ?></h3>

    <?php else : ?>

        <h3><?php _e( 'Billing Details', 'woocommerce' ); ?></h3>
<?
if($key=='billing_first_name')
{
?>
<p>Sei un privato cittadino, un'azienda o un libero professionista?</p>
<input type="radio" name="choice" value="privato_cittadino">Privato cittadino
<input type="radio" name="choice" value="azienda_professionista">Azienda o libero professionista<br>
<?
}
?>
    <?php endif; ?>

It works properly, but now I don't know how can I create the required fields like I described. Can you help me step by step? Please, consider I'm not a programmer.

Machos answered 5/9, 2016 at 19:59 Comment(2)
You could take a look at this link: cloudways.com/blog/custom-field-woocommerce-checkout-page they explain how to add custom fields with the usage of a plugin or with just plain code.Trafalgar
I think, there is a nice premium plugin for all your requirement without any code. themehigh.com/product/woocommerce-checkout-field-editor-proHepler
A
8

To answer the question, it will need to be done in 4 steps.

  1. Add 4 custom fields to the woocommerce checkout page. The way you have done it is not best practice and should be done through use of actions/filters.
  2. Validate the data when the request is made to the back-end, this is to make sure the user actually selected and entered what is required.
  3. Save the data to the order as post meta so it can be accessed later.
  4. Implement javascript toggle feature so that based on what the user selects for the first question, the related fields are then shown.

Adding custom fields to woocommerce checkout

You will need to find a suitable action for where you would like to add the fields. I would recommend using the action woocommerce_after_checkout_billing_form as it will display fields after all the personal/billing information.

if( !function_exists( 'custom_checkout_question_field' ) ) {
  /**
   * Add custom question field after the billing form fields
   *
   * @param Integer $order_id New order id
   */
  function custom_checkout_question_field( $checkout ) {

    echo "<div class='custom-question-field-wrapper custom-question-1'>";

    echo sprintf( '<p>%s</p>', __( "Sei un privato cittadino, un'azienda o un libero professionista?" ) );

    woocommerce_form_field( 'custom_question_field', array(
      'type'            => 'radio',
      'required'        => true,
      'class'           => array('custom-question-field', 'form-row-wide'),
      'options'         => array(
        'privato_cittadino'         => 'Privato cittadino',
        'azienda_professionista'    => 'Azienda o libero professionista',
      ),
    ), $checkout->get_value( 'custom_question_field' ) );

    woocommerce_form_field( 'custom_question_text_codice_fiscale', array(
      'type'            => 'text',
      'label'           => 'Codice Fiscale',
      'required'        => true,
      'class'           => array('custom-question-codice-fiscale-field', 'form-row-wide'),
    ), $checkout->get_value( 'custom_question_text_codice_fiscale' ) );

    woocommerce_form_field( 'custom_question_text_p_iva', array(
      'type'            => 'text',
      'label'           => 'P.Iva',
      'required'        => true,
      'class'           => array('custom-question-p-iva-field', 'form-row-wide'),
    ), $checkout->get_value( 'custom_question_text_p_iva' ) );

    woocommerce_form_field( 'custom_question_text_ragione_sociale', array(
      'type'            => 'text',
      'label'           => 'Ragione sociale',
      'required'        => true,
      'class'           => array('custom-question-ragione-sociale-field', 'form-row-wide'),
    ), $checkout->get_value( 'custom_question_text_ragione_sociale' ) );

    echo "</div>";

  }

  add_action( 'woocommerce_after_checkout_billing_form', 'custom_checkout_question_field' );
}

Javascript front-end toggle

You will need to add custom javascript in order to toggle the 3 additional fields depending on the question. I have created a php function which will output a html script tag with some javascript. This is then attached to the wp_footer action.

This is not recommended method and you should really separate it into a new file js and enqueue the file when needed.

See: https://codex.wordpress.org/Plugin_API/Action_Reference/wp_enqueue_scripts

if( !function_exists( 'custom_question_conditional_javascript' ) ) {
  function custom_question_conditional_javascript() {
    ?>
    <script type="text/javascript">
    (function() {

      // Check if jquery exists
      if(!window.jQuery) {
        return;
      };

      var $ = window.jQuery;

      $(document).ready(function() {

        var questionField       = $('.custom-question-field'),
            codiceFiscaleField  = $('.custom-question-codice-fiscale-field'),
            pIvaField           = $('.custom-question-p-iva-field'),
            ragioneSocialeField = $('.custom-question-ragione-sociale-field ');

        // Check that all fields exist
        if(
          !questionField.length ||
          !codiceFiscaleField.length ||
          !pIvaField.length ||
          !ragioneSocialeField.length
        ) {
          return;
        }

        function toggleVisibleFields() {
          var selectedAnswer = questionField.find('input:checked').val();

          if(selectedAnswer === 'privato_cittadino') {
            codiceFiscaleField.show();
            pIvaField.hide();
            ragioneSocialeField.hide();
          } else if(selectedAnswer === 'azienda_professionista') {
            codiceFiscaleField.hide();
            pIvaField.show();
            ragioneSocialeField.show();
          } else {
            codiceFiscaleField.hide();
            pIvaField.hide();
            ragioneSocialeField.hide();
          }
        }

        $(document).on('change', 'input[name=custom_question_field]', toggleVisibleFields);
        $(document).on('updated_checkout', toggleVisibleFields);

        toggleVisibleFields();

      });
    })();
    </script>
    <?php
  }

  add_action( 'wp_footer', 'custom_question_conditional_javascript', 1000 );
}

Getting fields from submitted post request

You will need to get the data from php $_POST array and also sanitise it to prevent sql injection or other malicious code. I have created a helper function which will grab all the fields by keys provided in an array and sanitise them using wordpress sanitize_text_field helper function.

This helper can then be used when validating and also adding post meta.

if( !function_exists( 'custom_checkout_question_get_field_values' ) ) {
  /**
   * Get all form field values based on user submitted post data
   *
   * @return Array Key/value pair of field values based on $_POST data
   */
  function custom_checkout_question_get_field_values() {
    $fields = [
      'custom_question_field'                       => '',
      'custom_question_text_codice_fiscale'     => '',
      'custom_question_text_p_iva'                => '',
      'custom_question_text_ragione_sociale'    => '',
    ];

    foreach( $fields as $field_name => $value ) {
      if( !empty( $_POST[ $field_name ] ) ) {
        $fields[ $field_name ] = sanitize_text_field( $_POST[ $field_name ] );
      } else {
        unset( $fields[ $field_name ] );
      }
    }

    return $fields;
  }
}

Validating fields on the back-end

Validation is important because front-end cannot be trusted, it is very easy for users to modify required fields on the front-end. You can use Woocommerce woocommerce_checkout_process action in order to validate the fields and add error messages if it does not meet what is required.

if( !function_exists( 'custom_checkout_question_field_validate' ) ) {
  /**
   * Custom woocommerce field validation to prevent user for completing checkout
   *
   * @param Integer $order_id New order id
   */
  function custom_checkout_question_field_validate() {
    $field_values = custom_checkout_question_get_field_values();

    if ( empty( $field_values['custom_question_field'] ) ) {
      wc_add_notice( 'Please select an answer for the question.', 'error' );
    }

    if (
      $field_values['custom_question_field'] === 'privato_cittadino' &&
      empty( $field_values['custom_question_text_codice_fiscale'] )
    ) {
      wc_add_notice( 'Please enter codice fiscale.', 'error' );
    }

    if (
      $field_values['custom_question_field'] === 'azienda_professionista' &&
      empty( $field_values['custom_question_text_p_iva'] )
    ) {
      wc_add_notice( 'Please enter p iva.', 'error' );
    }

    if (
      $field_values['custom_question_field'] === 'azienda_professionista' &&
      empty( $field_values['custom_question_text_ragione_sociale'] )
    ) {
      wc_add_notice( 'Please enter ragione sociale.', 'error' );
    }

  }

  add_action( 'woocommerce_checkout_process', 'custom_checkout_question_field_validate' );
}

Saving custom post meta to the order

You can use the woocommerce woocommerce_checkout_update_order_meta action in order to save additional post meta to the order post type. Here we will use the helper function custom_checkout_question_get_field_values created above to get all fields from php $_POST array and also sanitize them before saving each one to the post meta.

if( !function_exists( 'custom_checkout_question_field_save' ) ) {
  /**
   * Update order post meta based on submitted form values
   *
   * @param Integer $order_id New order id
   */
  function custom_checkout_question_field_save( $order_id ) {
    $field_values = custom_checkout_question_get_field_values();

    foreach( $field_values as $field_name => $value ) {
      if( !empty( $field_values[ $field_name ] ) ) {
        update_post_meta( $order_id, $field_name, $value );
      }
    }
  }

  add_action( 'woocommerce_checkout_update_order_meta', 'custom_checkout_question_field_save' );
}
Autotoxin answered 11/9, 2018 at 19:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.