WooCommerce. Скрытие полей заказа в зависимости от выбранного способа доставки

Бывает иногда нужно сделать так, чтобы в зависимости от способа доставки выводились разные поля на странице оформления заказа. Можно скрывать эти поля стилями или скриптом, но возникает проблема валидации: заказ невозможно будет отправить, потому что не заполнены обязательные поля. Пришлось придумать собственное решение.

Выглядит решение так

Скрытие полей заказа в зависимости от выбранного способа доставки

Внимание!
Весь код необходимо добавлять в файл functions.php через дочернюю тему или например пустой плагин. Прежде чем, вносить какие либо изменения, сделайте бекап сайта.

к содержанию

Шаг первый. Добавляем форму полей во фрагмент

В WooCommerce есть такой функционал фрагментов, в них можно добавлять нужный html и выводить в нужном месте. Итак, добавляем фрагмент

/*
 * Добавляем форму к фрагменту
 */
add_filter( 'woocommerce_update_order_review_fragments', 'artabr_add_update_form_billing' );
function artabr_add_update_form_billing( $fragments ) {
   ob_start();
   wc_get_template( 'checkout/form-billing.php', array(
      'checkout' => WC()->checkout(),
   ) );
   $art_add_update_form_billing              = ob_get_clean();
   $fragments['.woocommerce-billing-fields'] = $art_add_update_form_billing;
   
   return $fragments;
}
к содержанию

Шаг второй. Убираем лишние поля

Предполагается, что способы доставки настроены. Для примера созданы два способа. Теперь требуется указать нужный идентификатор способа доставки. Самый простой способ — посмотреть в исходном коде

Узнать идентификатор способа доставки

Выделенные строки и есть идентификаторы. Теперь достаточно сделать проверку и если получаем нужный способ доставки, удаляем лишние поля

/*
 * Убираем поля для конкретного способа доставки
 */
add_filter( 'woocommerce_checkout_fields', 'artabr_override_checkout_fields' );
function artabr_override_checkout_fields( $fields ) {
   $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
   if ( 'free_shipping:1' === $chosen_methods[0] ) {
      unset( $fields['billing']['billing_company'] );
      unset( $fields['billing']['billing_address_1'] );
      unset( $fields['billing']['billing_address_2'] );
      unset( $fields['billing']['billing_city'] );
      unset( $fields['billing']['billing_postcode'] );
      unset( $fields['billing']['billing_country'] );
      unset( $fields['billing']['billing_state'] );
      unset( $fields['billing']['billing_phone'] );
      unset( $fields['billing']['billing_email'] );
   }
   
   return $fields;
}

Это пример. В каждом случае, допиливайте под свой проект

к содержанию

Шаг третий. Обновление страницы

Формально все работает, вот только обновление страницы происходит только после обновления страницы. Добавим немного магии ajax

  • ловим выполнение обновления
  • ловим событие выбора способа доставки
  • запускаем прелоад
  • загружаем фрагмент из первого шага
/*
* Обновление формы
*/
add_action( 'wp_footer', 'artabr_add_script_update_shipping_method' );
function artabr_add_script_update_shipping_method() {
   if (is_checkout()) {
      ?>
      <script>
            jQuery(document).ready(function ($) {
                jQuery(document).ajaxComplete(function (event, xhr, settings) {
                    if (settings.url.indexOf('update_order_review') > -1) {
                        $('input[name^="shipping_method"]').on('change', function () {
                            $('.woocommerce-billing-fields').block({
                                message: null,
                                overlayCSS: {
                                    background: '#fff',
                                    'z-index': 1000000,
                                    opacity: 0.6
                                }
                            });
                        });
                        $(".woocommerce-billing-fields").html(xhr.responseJSON.fragments[".woocommerce-billing-fields"]);
                        $('.woocommerce-billing-fields').unblock();
                    }
                });
            });
      
      </script>
      <?php
   }
}

Вот как-то так. Код проверялся на стандартной теме StoreFront

к содержанию

Весь код полностью

Просто запихать в в файл functions.php

/*
 * Добавляем форму к фрагменту
 */
add_filter( 'woocommerce_update_order_review_fragments', 'artabr_add_update_form_billing' );
function artabr_add_update_form_billing( $fragments ) {
   ob_start();
   wc_get_template( 'checkout/form-billing.php', array(
      'checkout' => WC()->checkout(),
   ) );
   $art_add_update_form_billing              = ob_get_clean();
   $fragments['.woocommerce-billing-fields'] = $art_add_update_form_billing;
   
   return $fragments;
}

/*
 * Убираем поля для конкретного способа доставки
 */
add_filter( 'woocommerce_checkout_fields', 'artabr_override_checkout_fields' );
function artabr_override_checkout_fields( $fields ) {
   $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
   if ( 'free_shipping:1' === $chosen_methods[0] ) {
      unset( $fields['billing']['billing_company'] );
      unset( $fields['billing']['billing_address_1'] );
      unset( $fields['billing']['billing_address_2'] );
      unset( $fields['billing']['billing_city'] );
      unset( $fields['billing']['billing_postcode'] );
      unset( $fields['billing']['billing_country'] );
      unset( $fields['billing']['billing_state'] );
      unset( $fields['billing']['billing_phone'] );
      unset( $fields['billing']['billing_email'] );
   }
   
   return $fields;
}

/*
* Обновление формы
*/
add_action( 'wp_footer', 'artabr_add_script_update_shipping_method' );
function artabr_add_script_update_shipping_method() {
   if ( is_checkout() ) {
      ?>
      <script>
            jQuery(document).ready(function ($) {
                jQuery(document).ajaxComplete(function (event, xhr, settings) {
                    if (settings.url.indexOf('update_order_review') > -1) {
                        $('input[name^="shipping_method"]').on('change', function () {
                            $('.woocommerce-billing-fields').block({
                                message: null,
                                overlayCSS: {
                                    background: '#fff',
                                    'z-index': 1000000,
                                    opacity: 0.6
                                }
                            });
                        });
                        $(".woocommerce-billing-fields").html(xhr.responseJSON.fragments[".woocommerce-billing-fields"]);
                        $('.woocommerce-billing-fields').unblock();
                    }
                });
            });
      
      </script>
      <?php
   }
}

Вот и все. Не забудьте тыкнуть в кнопки Поделитья…

5 комментариев
  • Иван

    20.02.2018

    Здравствуйте. В принципе, метод рабочий. Есть один нюанс: как только происходят изменения, ввод текста, в полях фрагмента (адрес, город) данные которые были введены до того (Имя, Фамилия) очищаются. Подскажите, пожалуйста с чем может быть связано.

    • Артем

      22.02.2018

      Доброго! Есть такое. Скорее всего связано с тем, что обновляется вся форма с полями, потому и поля очищаются

      • Вячеслав

        03.04.2018

        а как решить — так и не написали….

        • Артем

          03.04.2018

          Пока не знаю, как разберусь, выложу обновление

          • Вячеслав

            04.04.2018

            спасибо, будем ждать! Главное — не забудьте :)

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *
php js HTML CSS Code