Show or hide registration fields based on selected

2020-03-31 04:19发布

问题:

I am trying to customize the registration form for my site. I've been using this guide and have successfully created/stored additional fields for my registration form. Guide to customized Registration.

I have created a drop-down/select field in my registration form for the user to select whether they want a Standard or Education account-type when registering:

If they select the Education account type, I want additional fields to appear so that I can collect additional data for their school. Is there a way for me to provide conditional logic for whether or not a field is visible based on the current value of another field in the form?

Here's kind of an example of what I would want to accomplish:

Can someone point me in the right direction to accomplish conditional form fields? Also, I do not want to use a third-party plugin for this. Having full control is important for this.

EDIT: As requested, here is the full code for my function:

    <?php
/*
Plugin Name: Custom Account Fields
Plugin Author: Case Silva
*/

//Create Custom Fields
if(!function_exists('get_custom_fields')){
    function get_custom_fields(){
        return apply_filters('custom_fields', array(
            'verified_education_acct' => array(
                'type' => 'checkbox',
                'label' => __('Verified?'),
                'required' => false,
                'hide_in_account' => true,
                'hide_in_admin' => false,
                'hide_in_registration' => true,
                'hide_in_checkout' => true
            ),
            'customer_id_num' => array(
                'type' => 'text',
                'label' => __('Customer ID# '),
                'placeholder' => __('e.g. 1234567890'),
                'required' => false,
                'hide_in_account' => true,
                'hide_in_admin' => false,
                'hide_in_checkout' => true,
                'hide_in_registration' => true
            ),
            'account_type' => array(
                'type' => 'select',
                'label' => __('What type of account will this be?'),
                'options' => array(
                    '' => __('Select an option...'),
                    1 => __('Education'),
                    2 => __('Standard')
                ),
                'required' => true,
                'hide_in_account' => true,
                'hide_in_admin' => false,
                'hide_in_checkout' => false,
                'hide_in_registration' => false
            ),
            'school_name' => array(
                'type' => 'text',
                'label' => __('School Name'),
                'placeholder' => __('e.g. North Middle School'),
                'required' => true,
                'hide_in_account' => 'account_type' != 1,
                'hide_in_admin' => false,
                'hide_in_checkout' => 'account_type' != 1,
                'hide_in_registration' => 'account_type' != 1
            ),
        ));
    }
}

//Add them to User Area
if(!function_exists('print_user_frontend_fields')){
    function print_user_frontend_fields(){
        $fields = get_custom_fields();
        $user_logged_in = is_user_logged_in();

        foreach ($fields as $key => $field_args) {
            if($user_logged_in && !empty($field_args['hide_in_account'])){
                continue;
            }
            if(! $user_logged_in && ! empty($field_args['hide_in_registration'])){
                continue;
            }
            woocommerce_form_field($key, $field_args);
        }
    }
}

//Add them to Admin Area
if(!function_exists('print_user_admin_fields')){
    function print_user_admin_fields(){
        $fields = get_custom_fields();

        ?>
        <h2><?php _e('Education/School Information'); ?></h2>
        <table class = "form-table" id = "additional-information">
            <tbody>
                <?php foreach ($fields as $key => $field_args) { ?>
                    <?php
                    if(! empty($field_args['hide_in_admin'])){
                        continue;
                    }

                    $user_id = get_edit_user_id();
                    $value = st_get_userdata($user_id, $key);
                    ?>
                    <tr>
                        <th>
                            <label for="<?php echo $key; ?>"><?php echo $field_args['label']; ?></label>
                        </th>
                        <td>
                            <?php $field_args['label'] = false; ?>
                            <?php woocommerce_form_field($key, $field_args, $value); ?>
                        </td>
                    </tr>
                <?php } ?>
            </tbody>
        </table>
        <?php
    }
}

//Save them to the database
if(!function_exists('save_acct_fields')){
    function save_acct_fields($customer_id){
        $fields = get_custom_fields();
        $sanitized_data = array();

        foreach ($fields as $key => $field_args) {
            if(! is_field_visible($field_args)){
                continue;
            }

            $sanitize = isset($field_args['sanitize']) ? $field_args['sanitize'] : 'wc_clean';
            $value = isset($_POST[$key]) ? call_user_func($sanitize, $_POST[$key]) : '';

            if(is_userdata($key)){
                $sanitized_data[$key] = $value;
                continue;
            }

            update_user_meta($customer_id, $key, $value);
        }

        if(! empty($sanitized_data)){
            $sanitized_data['ID'] = $customer_id;
            wp_update_user($sanitized_data);
        }
    }
}

//Check if field is visible on page
if(!function_exists('is_field_visible')){
    function is_field_visible($field_args){
        $visible = true;
        $action = filter_input(INPUT_POST, action);

        if(is_admin() && ! empty($field_args['hide_in_admin'])){
            $visible = false;
        } elseif((is_account_page() || $action === 'save_account_details') && is_user_logged_in() && ! empty($field_args['hide_in_account'])){
            $visible = false;
        } elseif((is_account_page() || $action === 'save_account_details') && ! is_user_logged_in() && ! empty($field_args['hide_in_registration'])){
            $visible = false;
        } elseif(is_checkout() && ! empty($field_args['hide_in_checkout'])){
            $visible = false;
        }
        return $visible;
    }
}

//Check if field is predefined
if(!function_exists('is_userdata')){
    function is_userdata($key){
        $userdata = array(
            'user_pass',
            'user_login',
            'user_nicename',
            'user_url',
            'user_email',
            'display_name',
            'nickname',
            'first_name',
            'last_name',
            'description',
            'rich_editing',
            'user_registered',
            'role',
            'jabber',
            'aim',
            'yim',
            'show_admin_bar_front'
        );
        return in_array($key, $userdata);
    }
}

//Populate form with submitted data
if(!function_exists('get_edit_user_id')){
    function get_edit_user_id(){
        return isset($_GET['user_id']) ? (int) $_GET['user_id'] : get_current_user_id();
    }
}

//Access saved data
if(!function_exists('st_get_userdata')){
    function st_get_userdata($user_id, $key){
        if(!is_userdata($key)){
            return get_user_meta($user_id, $key, true);         
        }

        $userdata = get_userdata($user_id);

        if(!$userdata || ! isset($userdata->{$key})){
            return '';
        }

        return $userdata->{$key};
    }
}

add_action('woocommerce_register_form', 'print_user_frontend_fields', 10);
add_action('woocommerce_edit_account_form', 'print_user_frontend_fields', 10);

add_action('show_user_profile', 'print_user_admin_fields', 30);
add_action('edit_user_profile', 'print_user_admin_fields', 30);

add_action('woocommerce_created_customer', 'save_acct_fields');
add_action('personal_options_update', 'save_acct_fields');
add_action('edit_user_profile_update', 'save_acct_fields');
add_action('woocommerce_save_account_details', 'save_acct_fields');
?>

回答1:

The only way to show hide fields is to use Javascript/jQuery as it's a event on client side.

So I have made some small changes to your code adding the necessary jQuery to handle Showing and hiding school_name text field depending on the account_type select field live event choice.

Here are the Two functions that I have changed in your code:

// Get custom fields
if(!function_exists('get_custom_fields')){
    function get_custom_fields(){
        return apply_filters('custom_fields', array(
            'verified_education_acct' => array(
                'type' => 'checkbox',
                'label' => __('Verified?'),
                'required' => false,
                'hide_in_account' => true,
                'hide_in_admin' => false,
                'hide_in_registration' => true,
                'hide_in_checkout' => true
            ),
            'customer_id_num' => array(
                'type' => 'text',
                'label' => __('Customer ID# (Acumatica)'),
                'placeholder' => __('e.g. 1234567890'),
                'required' => false,
                'hide_in_account' => true,
                'hide_in_admin' => false,
                'hide_in_checkout' => true,
                'hide_in_registration' => true
            ),
            'account_type' => array(
                'type' => 'select',
                'label' => __('What type of account will this be?'),
                'class' => array('form-row-wide'),
                'options' => array(
                    '' => __('Select an option...'),
                    1 => __('Education'),
                    2 => __('Standard')
                ),
                'required' => true,
                'hide_in_account' => true,
                'hide_in_admin' => false,
                'hide_in_checkout' => false,
                'hide_in_registration' => false,
                'js_trigger' => true, // <===  <=== Enabling Javascript 
            ),
            'school_name' => array(
                'type' => 'text',
                'label' => __('School Name'),
                'class' => array('form-row-wide off'), // <===  <===  Hidden field
                'placeholder' => __('e.g. North Middle School'),
                'required' => true,
                'hide_in_account' => false,
                'hide_in_admin' => false,
                'hide_in_checkout' => false,
                'hide_in_registration' => false,
                'js_triggered_by' => 'account_type', // <===  JS: field that trigger show/hide
                'js_show_val' => '1', // <===  <=== JS: selected field value that show this field 
            ),
        ));
    }
}

//Add them to User Area
if(!function_exists('print_user_frontend_fields')){
    function print_user_frontend_fields(){
        $fields = get_custom_fields();
        $user_logged_in = is_user_logged_in();
        $enable_js = false; // Initializing
        $data_js = []; // Initializing

        // Hiding conditional field (with "off" class)
        echo '<style>p.form-row.off{display:none;}</style>';

        foreach ($fields as $key => $field_args) {
            if($user_logged_in && !empty($field_args['hide_in_account'])){
                continue;
            }
            if(! $user_logged_in && ! empty($field_args['hide_in_registration'])){
                continue;
            }
            if( isset($field_args['js_trigger']) && $field_args['js_trigger'] ){
                $enable_js = true;
            }
            if( isset($field_args['js_triggered_by']) && $field_args['js_show_val'] ){
                $data_js[$key] = [ $field_args['js_triggered_by'] => $field_args['js_show_val'] ];
            }
            // Form fields output
            woocommerce_form_field($key, $field_args);
        }
        if( $user_logged_in || ! $enable_js ) return; // Exit

        // JQuery code
        ?>
        <script type="text/javascript">
        jQuery( function($){
            var a = <?php echo json_encode($data_js) ?>;
            $.each(a, function(b,o){
                $.each(o, function(k,v){
                    $('#'+k).on('change', function(){
                        var cf = '#'+b+'_field';
                        if ( $(this).val() == v && $(cf).hasClass('off') ) {
                            $(cf).removeClass('off');
                        } else if ( $(this).val() != v && ! $(cf).hasClass('off') ) {
                            $(cf).addClass('off');
                        }
                    });
                });
            });
        });
        </script>
        <?php
    }
}

Code goes in function.php file of your active child theme (or active theme). Tested and work.

1) On load, field is hidden.

2) On select "Education", the field is shown.

3) On select "Standard" (or nothing), the field is hidden.

to handle multiple fields you will need to make some changes, as this example is for one field.