【问题标题】:Add custom css class to WooCommerce checkout fields将自定义 CSS 类添加到 WooCommerce 结帐字段
【发布时间】:2014-05-29 22:04:43
【问题描述】:

我希望能够将自定义 CSS 类添加到我的 WooCommerce 结帐字段。我正在使用 twitter Bootstrap,我希望能够使用他们的 .form-control 类。

我查看了 form-billing.php 中的 woocommerce 模板文件夹,但我不确定将 .form-control 类添加到每个文本字段的位置。

这是form-billing.php的代码

<?php
/**
 * Checkout billing information form
 *
 * @author      WooThemes
 * @package     WooCommerce/Templates
 * @version     2.1.2
 */

 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 ?>
 <div class="woocommerce-billing-fields">
<?php if ( WC()->cart->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>

<?php endif; ?>

<?php do_action( 'woocommerce_before_checkout_billing_form', $checkout ); ?>

<?php foreach ( $checkout->checkout_fields['billing'] as $key => $field ) : ?>

    <?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>

<?php endforeach; ?>

<?php do_action('woocommerce_after_checkout_billing_form', $checkout ); ?>

<?php if ( ! is_user_logged_in() && $checkout->enable_signup ) : ?>

    <?php if ( $checkout->enable_guest_checkout ) : ?>

        <p class="form-row form-row-wide create-account">
            <input class="input-checkbox" id="createaccount" <?php checked( ( true === $checkout->get_value( 'createaccount' ) || ( true === apply_filters( 'woocommerce_create_account_default_checked', false ) ) ), true) ?> type="checkbox" name="createaccount" value="1" /> <label for="createaccount" class="checkbox"><?php _e( 'Create an account?', 'woocommerce' ); ?></label>
        </p>

    <?php endif; ?>

    <?php do_action( 'woocommerce_before_checkout_registration_form', $checkout ); ?>

    <?php if ( ! empty( $checkout->checkout_fields['account'] ) ) : ?>

        <div class="create-account">

            <p><?php _e( 'Create an account by entering the information below. If you are a returning customer please login at the top of the page.', 'woocommerce' ); ?></p>

            <?php foreach ( $checkout->checkout_fields['account'] as $key => $field ) : ?>

                <?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>

            <?php endforeach; ?>

            <div class="clear"></div>

        </div>

    <?php endif; ?>

    <?php do_action( 'woocommerce_after_checkout_registration_form', $checkout ); ?>

<?php endif; ?>
</div>

我需要查看另一个模板文件吗?

谢谢

【问题讨论】:

    标签: wordpress twitter-bootstrap woocommerce woothemes


    【解决方案1】:

    icc97 的回答差不多了,但是没用。

    我拿了icc97的回答,调试了一下:

    add_filter('woocommerce_checkout_fields', 'addBootstrapToCheckoutFields' );
    public function addBootstrapToCheckoutFields($fields) {
        foreach ($fields as &$fieldset) {
            foreach ($fieldset as &$field) {
                // if you want to add the form-group class around the label and the input
                $field['class'][] = 'form-group'; 
    
                // add form-control to the actual input
                $field['input_class'][] = 'form-control';
            }
        }
        return $fields;
    }
    

    【讨论】:

    • 如果我们只想为某些输入类型(即文本区域)添加类怎么办?
    • 请从此函数中删除public。这不是方法
    • 它对我有用。来自我的支持。
    【解决方案2】:

    正如@Peanuts 指出的那样,如果我们只想将 CSS 类添加到某些输入类型怎么办?

    在尝试了到目前为止发布的解决方案之后,(感谢大家!),我想出了一个使用简单“开关盒”的模组,其中的逻辑来自/woocommerce/includes/wc-template-functions.php。该函数允许我们一次定位所有输入类型,无论是默认输入类型还是自定义输入类型。

    无需重写woocommerce_form_field 函数来简单地更改输入类型的$defaults 参数。值得一提的是,该函数还允许我们向字段添加更多的 CSS 类。

    -- 这是函数--

    /*********************************************************************************************/
    /** WooCommerce - Modify each individual input type $args defaults /**
    /*********************************************************************************************/
    
    add_filter('woocommerce_form_field_args','wc_form_field_args',10,3);
    
    function wc_form_field_args( $args, $key, $value = null ) {
    
    /*********************************************************************************************/
    /** This is not meant to be here, but it serves as a reference
    /** of what is possible to be changed. /**
    
    $defaults = array(
        'type'              => 'text',
        'label'             => '',
        'description'       => '',
        'placeholder'       => '',
        'maxlength'         => false,
        'required'          => false,
        'id'                => $key,
        'class'             => array(),
        'label_class'       => array(),
        'input_class'       => array(),
        'return'            => false,
        'options'           => array(),
        'custom_attributes' => array(),
        'validate'          => array(),
        'default'           => '',
    );
    /*********************************************************************************************/
    
    // Start field type switch case
    
    switch ( $args['type'] ) {
    
        case "select" :  /* Targets all select input type elements, except the country and state select input types */
            $args['class'][] = 'form-group'; // Add a class to the field's html element wrapper - woocommerce input types (fields) are often wrapped within a <p></p> tag  
            $args['input_class'] = array('form-control', 'input-lg'); // Add a class to the form input itself
            //$args['custom_attributes']['data-plugin'] = 'select2';
            $args['label_class'] = array('control-label');
            $args['custom_attributes'] = array( 'data-plugin' => 'select2', 'data-allow-clear' => 'true', 'aria-hidden' => 'true',  ); // Add custom data attributes to the form input itself
        break;
    
        case 'country' : /* By default WooCommerce will populate a select with the country names - $args defined for this specific input type targets only the country select element */
            $args['class'][] = 'form-group single-country';
            $args['label_class'] = array('control-label');
        break;
    
        case "state" : /* By default WooCommerce will populate a select with state names - $args defined for this specific input type targets only the country select element */
            $args['class'][] = 'form-group'; // Add class to the field's html element wrapper 
            $args['input_class'] = array('form-control', 'input-lg'); // add class to the form input itself
            //$args['custom_attributes']['data-plugin'] = 'select2';
            $args['label_class'] = array('control-label');
            $args['custom_attributes'] = array( 'data-plugin' => 'select2', 'data-allow-clear' => 'true', 'aria-hidden' => 'true',  );
        break;
    
    
        case "password" :
        case "text" :
        case "email" :
        case "tel" :
        case "number" :
            $args['class'][] = 'form-group';
            //$args['input_class'][] = 'form-control input-lg'; // will return an array of classes, the same as bellow
            $args['input_class'] = array('form-control', 'input-lg');
            $args['label_class'] = array('control-label');
        break;
    
        case 'textarea' :
            $args['input_class'] = array('form-control', 'input-lg');
            $args['label_class'] = array('control-label');
        break;
    
        case 'checkbox' :  
        break;
    
        case 'radio' :
        break;
    
        default :
            $args['class'][] = 'form-group';
            $args['input_class'] = array('form-control', 'input-lg');
            $args['label_class'] = array('control-label');
        break;
        }
    
        return $args;
    }
    

    上面的功能完全解决了一次性锁定结帐表单输入的问题,这对于结帐表单默认输入类型甚至自定义新输入类型来说非常简单。不过,似乎不可能在不创建新函数的情况下打印每种输入类型的 html 输出,正如@abhisek 在他的回答中显示的那样。

    奖金

    似乎该功能还可能影响结帐页面之外由 WooCommerce 的功能或模板打印的其他表单字段。 我已经设法仅在结帐页面上使用is_page() 函数有条件地应用该函数。您的结帐页面可能有不同的 slug,因此请进行相应更改以反映它。

    如果您只需要在结账页面应用该功能,请执行以下操作:

    注释 add_filter()

    //add_filter('woocommerce_form_field_args','wc_form_field_args', 10, 3);

    并使用 add_action 代替

    add_action('woocommerce_form_field_args', 'wc_form_field_args', 10, 3);

    function wc_form_field_args( $args, $key, $value = null ) {
    
    ...
    
    // Right after 
        return $args;
    
    // Place the following
    
    if ( !is_page('checkout') ) {
      add_filter('woocommerce_form_field_args','wc_form_field_args', 10, 3);
    } else {
      remove_filter('woocommerce_form_field_args','wc_form_field_args', 10, 3);
    }
    
    
    }
    

    之后,该功能将只影响结帐页面表单。

    【讨论】:

    • @Monecchi 它可以工作,但它不仅仅影响结帐表格。有没有办法仅将其应用于结帐表单,同时仅针对某些字段类型(输入、文本区域、...)?
    • @Sefran2 我无法复制这个。该功能还有什么影响?为了只定位您想要的字段,只需从 switch() 函数中删除您不想要的案例。
    • @Sefran2 - 在进一步检查之后,确实似乎其他 woocommerce 的形式受到了该功能的影响。我刚刚使用is_page() 函数检查了结帐页面,以便在它不是结帐页面的情况下删除过滤器。我已经更新了函数。
    • @AdrianoMonecchi:如果add_filter被注释了,在action中添加和删除了什么?但是,您给了我一个提示,我在过滤器中添加了 if (is_checkout()),现在一切正常。谢谢:)
    • @Sefran2 请检查答案的“奖金”部分以获得解释。 add_action() 只是触发该功能,该功能反过来会条件检查您是否在结帐页面上,然后相应地添加或删除过滤器。我已经对其进行了测试,并且可以正常工作。然后,您必须再次修改该函数以仅针对您想要的字段类型。它不应该与结帐页面之外的 woocommerce 功能或模板打印的其他表单字段混淆。
    【解决方案3】:

    @Chetan 的 link and run 答案确实可以满足您的需求,但与以往一样,它们从来都不是很好的答案。

    最好的资源是 Customizing checkout fields using actions and filters 上的 WooCommerce Codex 页面。

    在 Chetan 页面的“自定义 WooCommerce 结帐字段标签和占位符文本”中,您需要将以下代码添加到您的 functions.php 中,我已经对其进行了修改,使其可以满足您的需求,但我没有测试过代码:

    // Hook in
    add_filter( 'woocommerce_checkout_fields' , 'my_theme_custom_override_checkout_fields' );
    
    // Our hooked in function - $fields is passed via the filter!
    function my_theme_custom_override_checkout_fields( $fields ) {
         foreach ($fields as $fieldset) {
             foreach ($fieldset as $field) {
                 $field['class'] = array('form-control');
             }
         }
         return $fields;
    }
    

    【讨论】:

    • 以上对我不起作用。相反,我挂上了woocommerce_form_field_args 过滤器,以便按如下方式传递类名:add_filter('woocommerce_form_field_args','wc_form_field_args',10,3); function wc_form_field_args($args, $key, $value) { $args['input_class'][] = 'form-control'; return $args; }
    • @AdrianoMonecchi 查看 Dan Smart 的 answer - 他调试了我的答案
    【解决方案4】:

    我通过定义自定义函数解决了这个问题。逻辑直接取自 wc-template-functions.php(我不确定这是否正确,但确实解决了问题)。

    /*
     * Custom form field function for Bootstrap 3
     */
    function bootstrap_woocommerce_form_field( $key, $args, $value = null ) {
        $defaults = array(
            'type'              => 'text',
            'label'             => '',
            'placeholder'       => '',
            'maxlength'         => false,
            'required'          => false,
            'class'             => array(),
            'label_class'       => array(),
            'input_class'       => array(),
            'return'            => false,
            'options'           => array(),
            'custom_attributes' => array(),
            'validate'          => array(),
            'default'           => '',
        );
    
        $args = wp_parse_args( $args, $defaults  );
    
        if ( ( ! empty( $args['clear'] ) ) ) $after = '<div class="clear"></div>'; else $after = '';
    
        if ( $args['required'] ) {
            $args['class'][] = 'validate-required';
            $required = ' <abbr class="required" title="' . esc_attr__( 'required', 'woocommerce'  ) . '">*</abbr>';
        } else {
            $required = '';
        }
    
        $args['maxlength'] = ( $args['maxlength'] ) ? 'maxlength="' . absint( $args['maxlength'] ) . '"' : '';
    
        if ( is_string( $args['label_class'] ) )
            $args['label_class'] = array( $args['label_class'] );
    
        if ( is_null( $value ) )
            $value = $args['default'];
    
        // Custom attribute handling
        $custom_attributes = array();
    
        if ( ! empty( $args['custom_attributes'] ) && is_array( $args['custom_attributes'] ) )
            foreach ( $args['custom_attributes'] as $attribute => $attribute_value )
                $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
    
        if ( ! empty( $args['validate'] ) )
            foreach( $args['validate'] as $validate )
                $args['class'][] = 'validate-' . $validate;
    
        switch ( $args['type'] ) {
        case "country" :
    
            $countries = $key == 'shipping_country' ? WC()->countries->get_shipping_countries() : WC()->countries->get_allowed_countries();
    
            if ( sizeof( $countries ) == 1 ) {
    
                $field = '<div class="form-group form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
    
                if ( $args['label'] )
                    $field .= '<label class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label']  . '</label>';
    
                $field .= '<strong>' . current( array_values( $countries ) ) . '</strong>';
    
                $field .= '<input type="hidden" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" value="' . current( array_keys($countries ) ) . '" ' . implode( ' ', $custom_attributes ) . ' class="country_to_state" />';
    
                $field .= '</div>' . $after;
    
            } else {
    
                $field = '<div class="form-group form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">'
                        . '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label'] . $required  . '</label>'
                        . '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" class="country_to_state form-control country_select" ' . implode( ' ', $custom_attributes ) . '>'
                        . '<option value="">'.__( 'Select a country&hellip;', 'woocommerce' ) .'</option>';
    
                foreach ( $countries as $ckey => $cvalue )
                    $field .= '<option value="' . esc_attr( $ckey ) . '" '.selected( $value, $ckey, false ) .'>'.__( $cvalue, 'woocommerce' ) .'</option>';
    
                $field .= '</select>';
    
                $field .= '<noscript><input type="submit" name="woocommerce_checkout_update_totals" value="' . __( 'Update country', 'woocommerce' ) . '" /></noscript>';
    
                $field .= '</div>' . $after;
    
            }
    
            break;
        case "state" :
    
            /* Get Country */
            $country_key = $key == 'billing_state'? 'billing_country' : 'shipping_country';
    
            if ( isset( $_POST[ $country_key ] ) ) {
                $current_cc = wc_clean( $_POST[ $country_key ] );
            } elseif ( is_user_logged_in() ) {
                $current_cc = get_user_meta( get_current_user_id() , $country_key, true );
                if ( ! $current_cc) {
                    $current_cc = apply_filters('default_checkout_country', (WC()->customer->get_country()) ? WC()->customer->get_country() : WC()->countries->get_base_country());
                }
            } elseif ( $country_key == 'billing_country' ) {
                $current_cc = apply_filters('default_checkout_country', (WC()->customer->get_country()) ? WC()->customer->get_country() : WC()->countries->get_base_country());
            } else {
                $current_cc = apply_filters('default_checkout_country', (WC()->customer->get_shipping_country()) ? WC()->customer->get_shipping_country() : WC()->countries->get_base_country());
            }
    
            $states = WC()->countries->get_states( $current_cc );
    
            if ( is_array( $states ) && empty( $states ) ) {
    
                $field  = '<div class="form-group form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field" style="display: none">';
    
                if ( $args['label'] )
                    $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label'] . $required . '</label>';
                $field .= '<input type="hidden" class="hidden" name="' . esc_attr( $key )  . '" id="' . esc_attr( $key ) . '" value="" ' . implode( ' ', $custom_attributes ) . ' placeholder="' . esc_attr( $args['placeholder'] ) . '" />';
                $field .= '</div>' . $after;
    
            } elseif ( is_array( $states ) ) {
    
                $field  = '<div class="form-group form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
    
                if ( $args['label'] )
                    $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label']. $required . '</label>';
                $field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" class="state_select form-control " ' . implode( ' ', $custom_attributes ) . ' placeholder="' . esc_attr( $args['placeholder'] ) . '">
                    <option value="">'.__( 'Select a state&hellip;', 'woocommerce' ) .'</option>';
    
                foreach ( $states as $ckey => $cvalue )
                    $field .= '<option value="' . esc_attr( $ckey ) . '" '.selected( $value, $ckey, false ) .'>'.__( $cvalue, 'woocommerce' ) .'</option>';
    
                $field .= '</select>';
                $field .= '</div>' . $after;
    
            } else {
    
                $field  = '<div class="form-group form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
    
                if ( $args['label'] )
                    $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label']. $required . '</label>';
                $field .= '<input type="text" class="form-control input-text ' . implode( ' ', $args['input_class'] ) .'" value="' . esc_attr( $value ) . '"  placeholder="' . esc_attr( $args['placeholder'] ) . '" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" ' . implode( ' ', $custom_attributes ) . ' />';
                $field .= '</div>' . $after;
    
            }
    
            break;
        case "textarea" :
    
            $field = '<div class="form-group form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
    
            if ( $args['label'] )
                $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label']. $required  . '</label>';
    
            $field .= '<textarea name="' . esc_attr( $key ) . '" class="form-control input-text ' . implode( ' ', $args['input_class'] ) .'" id="' . esc_attr( $key ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '"' . ( empty( $args['custom_attributes']['rows'] ) ? ' rows="2"' : '' ) . ( empty( $args['custom_attributes']['cols'] ) ? ' cols="5"' : '' ) . implode( ' ', $custom_attributes ) . '>'. esc_textarea( $value  ) .'</textarea>
                </div>' . $after;
    
            break;
        case "checkbox" :
    
            $field = '<div class="checkbox form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">
                    <label for="' . esc_attr( $key ) . '" class="checkbox ' . implode( ' ', $args['label_class'] ) .'" ' . implode( ' ', $custom_attributes ) . '>
                        <input type="' . esc_attr( $args['type'] ) . '" class="input-checkbox" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" value="1" '.checked( $value, 1, false ) .' />'
                        . $args['label'] . $required . '</label>
                </div>' . $after;
    
            break;
        case "password" :
    
            $field = '<div class="form-group form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
    
            if ( $args['label'] )
                $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label']. $required . '</label>';
    
            $field .= '<input type="password" class="form-control input-text ' . implode( ' ', $args['input_class'] ) .'" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" value="' . esc_attr( $value ) . '" ' . implode( ' ', $custom_attributes ) . ' />
                </div>' . $after;
    
            break;
        case "text" :
    
            $field = '<div class="form-group form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
    
            if ( $args['label'] )
                $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label'] . $required . '</label>';
    
            $field .= '<input type="text" class="form-control input-text ' . implode( ' ', $args['input_class'] ) .'" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" '.$args['maxlength'].' value="' . esc_attr( $value ) . '" ' . implode( ' ', $custom_attributes ) . ' />
                </div>' . $after;
    
            break;
        case "select" :
    
            $options = '';
    
            if ( ! empty( $args['options'] ) )
                foreach ( $args['options'] as $option_key => $option_text )
                    $options .= '<option value="' . esc_attr( $option_key ) . '" '. selected( $value, $option_key, false ) . '>' . esc_attr( $option_text ) .'</option>';
    
                $field = '<div class="form-group form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
    
                if ( $args['label'] )
                    $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label']. $required . '</label>';
    
                $field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" class="select form-control" ' . implode( ' ', $custom_attributes ) . '>
                        ' . $options . '
                    </select>
                </div>' . $after;
    
            break;
        default :
    
            $field = apply_filters( 'woocommerce_form_field_' . $args['type'], '', $key, $args, $value );
    
            break;
        }
    
        if ( $args['return'] ) return $field; else echo $field;
    }
    

    不要忘记将所有出现的woocommerce_form_field 替换为bootstrap_woocommerce_form_field 希望对您有所帮助!

    【讨论】:

      猜你喜欢
      • 2022-01-03
      • 2017-09-17
      • 2015-10-08
      • 2022-01-25
      • 2023-04-10
      • 2021-04-30
      • 2020-06-09
      相关资源
      最近更新 更多