如何将 2 select 字段(组合框)添加到 woocommerce 结帐页面?

How to add 2 select fields (combobox) to woocommerce checkout page?

我正在开发一个根据邮政编码提供本地交货日期的在线商店。我使用此代码段

限制了带有 selection 的邮政编码
add_filter ('woocommerce_default_address_fields', 'custom_override_default_postcode_field');
function custom_override_default_postcode_field ($address_fields) {
    // Zip codes
    $postcode_array = array (
        '28001' => '28001',
        '28002' => '28002',
        '28923' => '28923'
    );
    $address_fields['postcode']['type']    = 'select';
    $address_fields['postcode']['options'] = $postcode_array;
    return $address_fields;
}

我正在使用插件 woocommerce checkout field 编辑器,我添加了“交货天数”字段,这是一个 select 字段,其值是星期一、星期二、星期三 ...

现在,我想根据我客户的规范使第二个字段依赖于第一个字段,例如:

邮政编码 28001 / 周一和周三送货日

邮政编码 28002 / 周二和周四送货日

邮政编码 28923 / 周五和周日送货日

即买家选择邮政编码时,只显示他选择对应的日子。

如果有没有插件的方法我觉得会更好

非常感谢您的帮助, 路易斯

这需要大量的定制。试试下面的代码。代码转到您的活动主题 functions.php 文件。

add_filter ('woocommerce_default_address_fields', 'custom_override_default_postcode_field');
function custom_override_default_postcode_field ($address_fields) {
    // Zip codes
    $postcode_array = array (
        '28001' => '28001',
        '28002' => '28002',
        '28923' => '28923'
    );
    $address_fields['postcode']['type']    = 'select';
    $address_fields['postcode']['options'] = $postcode_array;
    return $address_fields;
}

您可以使用 woocommerce_checkout_fields 过滤器挂钩添加新的下拉字段 Delivery days

add_filter( 'woocommerce_checkout_fields' , 'custom_delivery_days_woocommerce_billing_fields' );
function custom_delivery_days_woocommerce_billing_fields( $fields ) {
    
     $fields['billing']['delivery_days'] = array(
        'label'       => __('Delivery days', 'woocommerce'),
        'placeholder' => _x('dropdown', 'placeholder', 'woocommerce'),
        'required'    => true,
        'class'       => array('form-row-wide'),
        'clear'       => true,
        'priority'    => 95,
        'type'        => 'custom_select',
        'options'     => array(
            'monday' => array(
                'label' =>  __('Monday', 'woocommerce' ),
                'data_attr_name'  => 'post-code',
                'data_attr_value' => '28001',
            ),
            'tuesday' => array(
                'label' =>  __('Tuesday', 'woocommerce' ),
                'data_attr_name'  => 'post-code',
                'data_attr_value' => '28002',
            ),
            'wednesday' => array(
                'label' =>  __('Wednesday', 'woocommerce' ),
                'data_attr_name'  => 'post-code',
                'data_attr_value' => '28001',
            ),
            'thursday' => array(
                'label' =>  __('Thursday', 'woocommerce' ),
                'data_attr_name'  => 'post-code',
                'data_attr_value' => '28002',
            ),
            'friday' => array(
                'label' =>  __('Friday', 'woocommerce' ),
                'data_attr_name'  => 'post-code',
                'data_attr_value' => '28923',
            ),
            'sunday' => array(
                'label' =>  __('Sunday', 'woocommerce' ),
                'data_attr_name'  => 'post-code',
                'data_attr_value' => '28923',
            )
        )
     );

     return $fields;
}

现在,根据您的要求,我将根据另一个 select 选项将数据属性用于显示隐藏 select 选项。但在 woocommerce 默认 select 下拉列表中,现在有一种方法可以将数据属性添加到 select。为此,我创建了 custom_select 类型,以便我们可以添加数据属性。正如您在上面看到的 woocommerce_checkout_fields 过滤器挂钩,我设置了 'type' => 'custom_select',.

您可以使用 woocommerce_form_field 过滤器挂钩添加新的自定义字段类型。

add_filter( 'woocommerce_form_field', 'add_custom_select', 10 , 4 );
function add_custom_select( $field, $key, $args, $value  ){

    if( $args['type'] == 'custom_select' ){

        if ( $args['required'] ) {
            $args['class'][] = 'validate-required';
            $required        = '&nbsp;<abbr class="required" title="' . esc_attr__( 'required', 'woocommerce' ) . '">*</abbr>';
        } else {
            $required = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
        }

        $field   = '';
        $options = '';

        if ( ! empty( $args['options'] ) ) {
            foreach ( $args['options'] as $option_key => $option_text ) {
                if ( '' === $option_key ) {
                    // If we have a blank option, select2 needs a placeholder.
                    if ( empty( $args['placeholder'] ) ) {
                        $args['placeholder'] = $option_text['label'] ? $option_text['label'] : __( 'Choose an option', 'woocommerce' );
                    }
                    $custom_attributes[] = 'data-allow_clear="true"';
                }
                $options .= '<option value="' . esc_attr( $option_key ) . '" ' . selected( $value, $option_key, false ) . ' data-'.$option_text['data_attr_name'].'="'.$option_text['data_attr_value'].'" >'  . esc_html( $option_text['label'] ) . '</option>';
            }

            $field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="select ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" ' . implode( ' ', $custom_attributes ) . ' data-placeholder="' . esc_attr( $args['placeholder'] ) . '">
                    ' . $options . '
                </select>';
        }

        $field_container = '<p class="form-row %1$s" id="%2$s" data-priority="' . esc_attr( $sort ) . '">%3$s</p>';
        
        if ( ! empty( $field ) ) {
            $field_html = '';

            if ( $args['label'] && 'checkbox' !== $args['type'] ) {
                $field_html .= '<label for="' . esc_attr( $label_id ) . '" class="' . esc_attr( implode( ' ', $args['label_class'] ) ) . '">' . wp_kses_post( $args['label'] ) . $required . '</label>';
            }

            $field_html .= '<span class="woocommerce-input-wrapper">' . $field;

            if ( $args['description'] ) {
                $field_html .= '<span class="description" id="' . esc_attr( $args['id'] ) . '-description" aria-hidden="true">' . wp_kses_post( $args['description'] ) . '</span>';
            }

            $field_html .= '</span>';

            $container_class = esc_attr( implode( ' ', $args['class'] ) );
            $container_id    = esc_attr( $args['id'] ) . '_field';
            $field           = sprintf( $field_container, $container_class, $container_id, $field_html );
        }

        return $field;

    }

    return $field;

}

现在在 billing_postcode 更改中,您必须获得需要与 delivery_days 下拉选项 data-post-code 进行比较的 billing_postcode 值,并基于此您可以显示隐藏。

function add_custom_js(){
    ?>
    <script type="text/javascript">
        (function($){
            $('#billing_postcode').on('change', function(){
            var postcode = $(this).val();
            var days  = $('#delivery_days');
            var i     = 1;
            $('option', days).filter(function(){
                if ( $(this).attr('data-post-code') === postcode ) {
                    $(this).show();
                    if( i == 1 ){
                      $("#delivery_days").val($(this).val());
                    }
                    i++;
                } else {
                    $(this).hide();
                }
            });
            });
            $('#billing_postcode').trigger('change');
        })(jQuery);
    </script>
    <?php
}
add_action( 'wp_footer', 'add_custom_js', 10, 1 );

已测试并有效。