Ошибка в другом обязательном поле

Ни для кого не секрет, что онлайн-формы могут стать серьёзным испытанием для пользователей. Особенно когда они выглядят как список полей для ввода без каких-либо подсказок. Однако мы, как разработчики, можем значительно облегчить жизнь посетителям наших сайтов.

Используем CSS

В CSS существует четыре специальных псевдокласса, применимых к полям формы: :valid (валидное поле), :invalid (невалидное), :required (обязательное) и :optional (необязательное). Их можно использовать, чтобы добавлять некоторые — хотя и весьма ограниченные — подсказки пользователям, заполняющим форму.

Используя :valid и :invalid, мы можем показать пользователю, правильно ли заполнено поле по мере ввода.

input:valid {
  border-color: green;
}

input:invalid {
  border-color: red;
}

Стилизация псевдоклассов :valid и :invalid

Стилизация псевдоклассов : valid и : invalid

Однако с этим способом связана одна проблема: стили применяются до того, как пользователь начнёт работу с формой. Поля, обязательные для заполнения, сразу подсветятся нам как :invalid, а необязательные — как :valid. Это значит, что пользователь, даже не приступив к заполнению формы, может сразу же получить негативную обратную связь. Не очень-то хорошо.

Стилизация состояний :required и :optional сама по себе не особо полезна, поскольку эта информация обычно указывается в подписях к полям формы. Однако мы можем объединить эти состояния с псевдоклассами :valid / :invalid и стилизовать их комбинации. Например, мы хотим показывать лишь положительный результат, когда валидно обязательное к заполнению поле.

input:required:valid {
  border-color: green;
}

Стилизация по :valid и :required

Стилизация по : valid и : required

Используем JavaScript

JavaScript даёт намного больше возможностей для улучшения работы пользователей с формами. Давайте рассмотрим в качестве примера три числовых поля, у каждого из которых установлен минимум в 10, максимум в 100 и шаг в 10 единиц.

<form>
  <label>
    Number Input 1
   <input type="number" min="10" max="100" step="10">
  </label>

  <label>
    Number Input 2
   <input type="number" min="10" max="100" step="10">
  </label>

  <label>
    Number Input 3
   <input type="number" min="10" max="100" step="10">
  </label>

  <input type="submit">
</form>

Устанавливая атрибуты minmax и step, мы можем быть уверены в правильности значения только тогда, когда пользователь использует специальные контролы числового поля. Но что мешает пользователю ввести вручную некорректные данные? Вот что произойдёт, если он вставит 112 и 123 в три поля и отправит форму:

Стандартный тултип валидации

Стандартный тултип валидации

В результате всё, что получит пользователь — это сообщение об ошибке для первого поля. Кроме того, в этом сообщении будет указано лишь одно несоответствие из двух требуемых. Такое поведение можно исправить, изменяя показываемые валидатором сообщения.

Добавляем несколько сообщений об ошибках в один тултип

Валидируя поля, браузер проверяет их по определённому списку потенциальных ошибок. В каждом поле содержится специальный объект validity, включающий в себя список булевых значений, характеризующих ту или иную проверку на валидность. Например, вот такой validity-объект будет у поля, когда пользователь введёт в него 1:

input.validity = {
  valid: false // Поле валидно
  customError: false // Установленно специальное сообщение ошибки
  patternMismatch: false // Значение не удовлетворяет шаблону, установленному в атрибуте pattern
  rangeOverflow: false // Значение превосходит атрибут max
  rangeUnderflow: true // Значение меньше атрибута min
  stepMismatch: true // Значение не соответствует указаному шагу
  tooLong: false // Значение слишком длинное
  tooShort: false // Значение слишком короткое
  typeMismatch: false // Значение не соответствует указаному атрибуту type
  valueMissing: false // Отсутствует обязательное значение
};

Примечание переводчика: Слово «mismatch» переводится как «несоответствие». Поэтому в значениях patternMismatchstepMismatch и typeMismatch обратная логика: true — значение не удовлетворяет атрибуту, false — удовлетворяет.

По умолчанию браузер отобразит лишь одну ошибку. Что мы можем сделать, так это проверить все эти значения самостоятельно и, если найдутся ошибки, сохранить их. Как только мы сохраним все ошибки для одного поля, мы можем отобразить весь их список в виде специального сообщения об ошибке при помощи функции setCustomValidity().

function CustomValidation() { }

CustomValidation.prototype = {
  // Установим пустой массив сообщений об ошибках
  invalidities: [],

  // Метод, проверяющий валидность
  checkValidity: function(input) {

    var validity = input.validity;

    if (validity.patternMismatch) {
      this.addInvalidity('This is the wrong pattern for this field');
    }

    if (validity.rangeOverflow) {
      var max = getAttributeValue(input, 'max');
      this.addInvalidity('The maximum value should be ' + max);
    }

    if (validity.rangeUnderflow) {
      var min = getAttributeValue(input, 'min');
      this.addInvalidity('The minimum value should be ' + min);
    }

    if (validity.stepMismatch) {
      var step = getAttributeValue(input, 'step');
      this.addInvalidity('This number needs to be a multiple of ' + step);
    }

    // И остальные проверки валидности...
  },

  // Добавляем сообщение об ошибке в массив ошибок
  addInvalidity: function(message) {
    this.invalidities.push(message);
  },

  // Получаем общий текст сообщений об ошибках
  getInvalidities: function() {
    return this.invalidities.join('. n');
  }
};

// Добавляем обработчик клика на кнопку отправки формы
submit.addEventListener('click', function(e) {
  // Пройдёмся по всем полям
  for (var i = 0; i < inputs.length; i++) {

    var input = inputs[i];

    // Проверим валидность поля, используя встроенную в JavaScript функцию checkValidity()
    if (input.checkValidity() == false) {

      var inputCustomValidation = new CustomValidation(); // Создадим объект CustomValidation
      inputCustomValidation.checkValidity(input); // Выявим ошибки
      var customValidityMessage = inputCustomValidation.getInvalidities(); // Получим все сообщения об ошибках
      input.setCustomValidity(customValidityMessage); // Установим специальное сообщение об ошибке

    } // закончился if
  } // закончился цикл
});

Теперь при попытке отправить форму мы увидим вот это:

Отображаем несколько ошибок в одном тултипе

Стало лучше, поскольку теперь будут показываться все сообщения об ошибках, связанные с конкретным полем. Однако другая проблема всё ещё не решена: ошибки по-прежнему показываются лишь для первого поля.

Это ограничение валидации, устанавливаемое браузером. Чтобы его побороть, нам нужно пойти другим путём.

Показываем все ошибки для всех полей

Вместо того, чтобы использовать встроенный тултип, мы можем добавлять сообщения об ошибках напрямую в DOM. Таким образом, все ошибки будут выводиться рядом с соответствующим полем.

Этого можно добиться какой-то парой дополнительных строчек в нашем коде:

CustomValidation.prototype.getInvaliditiesForHTML = function() {
  return this.invalidities.join('. <br>');
}

// Добавляем обработчик клика на кнопку отправки формы
submit.addEventListener('click', function(e) {
  // Пройдёмся по всем полям
  for (var i = 0; i < inputs.length; i++) {

    var input = inputs[i];

    // Проверим валидность поля, используя встроенную в JavaScript функцию checkValidity()
    if (input.checkValidity() == false) {

      var inputCustomValidation = new CustomValidation(); // Создадим объект CustomValidation
      inputCustomValidation.checkValidity(input); // Выявим ошибки
      var customValidityMessage = inputCustomValidation.getInvalidities(); // Получим все сообщения об ошибках
      input.setCustomValidity(customValidityMessage); // Установим специальное сообщение об ошибке

      // Добавим ошибки в документ
      var customValidityMessageForHTML = inputCustomValidation.getInvaliditiesForHTML();
      input.insertAdjacentHTML('afterend', '<p class="error-message">' + customValidityMessageForHTML + '</p>')
      stopSubmit = true;

    } // закончился if
  } // закончился цикл

  if (stopSubmit) {
    e.preventDefault();
  }
});

Вот что происходит при клике на submit теперь:

Отображаем все ошибки для всех полей в DOM

Отображаем все ошибки для всех полей в DOM

Используем нестандартные проверки валидности

Иногда встроенной в браузер валидации бывает недостаточно. Нам может понадобиться, чтобы вводимые данные удовлетворяли некоторым дополнительным правилам. Например, чтобы в текстовом поле требовалось указать особые символы.

Так как мы уже проверяем все возможные ошибки вручную в нашей функции CustomValidation.prototype.checkValidity, мы можем просто-напросто добавить туда ещё несколько проверок.

CustomValidation.prototype.checkValidity = function(input) {

  // Тут идут встроенные проверки валидности

  // А тут специальные
  if (!input.value.match(/[a-z]/g)) {
    this.addInvalidity('At least 1 lowercase letter is required');
  }

  if (!input.value.match(/[A-Z]/g)) {
    this.addInvalidity('At least 1 uppercase letter is required');
  }
};

Валидация в реальном времени

Хотя текущий способ выглядит намного лучше, он тоже не без изъянов. Наихудший из недочётов заключается в том, что пользователь не сможет увидеть никаких сообщений, пока не нажмёт на кнопку отправки формы. Было бы гораздо лучше, если бы валидация поля происходила сразу же при его заполнении. Можно выделить три правила для того, чтобы с формой было удобно работать:

  1. Требования для каждого поля чётко видны до того, как пользователь начал печатать.
  2. Как только пользователь начинает вводить данные, соблюдая требования, он сразу видит индикатор успешного заполнения поля или подсказки, если есть ошибки.
  3. Нужно отображать сообщения об ошибках таким образом, чтобы пользователь не мог отправить некорректно заполненную форму.

Пример валидации в реально времени

Пример валидации в реально времени

Если вы хотите попробовать свои силы (и даже сделать получше), вы можете воспользоваться вот этим шаблоном.


«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.

ТелеграмПодкастБесплатные учебники

Содержание:

1.Ошибка в файлах внешних обработок, отчетах и доработанных программных продуктах.

2. Ошибка «Поле объекта не обнаружено» в 1С 8.3 при обновлении неизмененной конфигурации.

«Поле объекта не обнаружено» — ошибка, которая встречается довольно часто при работе с программными продуктами 1С:Предприятие. Часто она возникает после обновления программы. Рассмотрим подробнее, в чем ее причины и как с ней бороться.  

1.      Ошибка в файлах внешних обработок, отчетах и доработанных программных продуктах.


Чаще всего ошибка возникает после обновления в файлах внешних обработок, отчетах, либо дописанных блоках программы, – в том функционале, который не входил в основную поставку 1С. В данном случае ошибка «Поле объекта не обнаружено» означает, что программа пытается обратиться к полю, которого больше нет или имя которого было изменено.

Первой причиной этого может быть решение производителей. Разработчики программного продукта 1С решили, что данное поле (переменная, реквизит и т.д.) им больше не нужно или переименовали его в целях методической правильности. После обновления в дописанном функционале остались места, где используется измененный или удаленный реквизит. Поскольку разработчики программного продукта фирмы «1С» не могли знать о внесенных изменениях, программа не сможет заменить своим кодом ту часть кода, где используется измененный или удаленный реквизит. Решение в этом случае: найти место, в котором возникает ошибка, и исправить имя поля (реквизита, переменной, и т.д.) или изменить способ получения данных. Например, адрес контрагента в 1С раньше был реквизитом справочника, а в новом релизе хранится в регистре сведений Контактная информация.

Как правило, данные в программных продуктах 1С не исчезают «в никуда», если некое поле было удалено разработчиками, значит информация, которую оно хранило, перенесена в другое поле (реквизит, переменную, и т.д).

Второй причиной может стать ошибка при проведении обновления – и это относится только к доработанным конфигурациям и не затрагивает внешние отчеты и обработки. В этой ситуации специалист при обновлении случайно «затер» дописанное поле (реквизит, переменную, и т.д.). Понять это можно, сравнив обновленную базу с копией базы, и сравнив конфигурацию текущей базы с типовой (Конфигурация – поддержка – сравнить, объединить). Решение может зависеть от того, что конкретно было «затерто». Но как правило, если ошибка была допущена при обновлении, нельзя знать наверняка — единственная ли это ошибка. Поэтому наилучший выход – восстановить базу из копии и провести обновление снова.

К сожалению, если дело касается переписанных блоков конфигураций или внешних обработок и отчетов, без достаточно глубокого знания программных продуктов 1С невозможно самостоятельно понять, как исправить «Поле объекта не обнаружено». Для решения проблемы стоит пригласить специалиста, потому как причина в каждом конкретном случае может быть своя.

Если вы точно уверенны, что работаете с неизмененной конфигурацией, и ошибка возникает при работе исключительно с типовым функционалом, тогда есть несколько способов, которые могут помочь решить проблему.  

2. Ошибка «Поле объекта не обнаружено» в 1С 8.3 при обновлении неизмененной конфигурации.

Иногда ошибка «Поле объекта не обнаружено» в 1С 8.3 возникает при обновлении типовых конфигураций. Причин и решений ошибки может быть несколько:

1). Изменение платформы.
Ошибка может возникать, когда в обновленной конфигурации используются основные механизмы платформы, которые в используемой версии платформы еще не реализованы. Ситуация может быть и обратной. Поэтому одно из правильных решений – обновить платформу до последнего релиза 1С 8.3 либо попытаться использовать более старый, но подходящий релиз платформы.

Узнать, какой релиз платформы подходит для вашей конфигурации, можно на сайте releases.1c.ru, нажав на поле Порядок обновления 1С.

2). Тестирование и исправление 1С
Во время работы с базой и во время ее обновления бывают ситуации, когда база данных может быть повреждена. В таких случаях базу нужно чинить. Сделать это можно с помощью Тестирования и исправления 1С внутри самой конфигурации (в конфигураторе открыть Администрирование — Тестирование и исправление). Перед любым тестированием обязательно нужно сделать копию базы данных. При тестировании должны стоять галки «Проверка ссылочной целостности информационной базы» и «Проверка логической целостности информационной базы», имеет смысл еще поставить галку «Реструктуризация таблиц информационной базы». Далее нужно выбрать поле «Тестирование и исправление». В блоке «При наличии ссылок на несуществующие объекты» выбрать пункт «Очищать ссылки». А в блоке «При частичной потере данных объектов» выбрать «Удалять объекты». Затем нажать кнопку «Выполнить».

Если это не помогло, можно также попытаться использовать утилиту сhdbfl. Она находится в папке bin в установленной платформе.

 

3). Очистка настроек пользователей

Ошибка может появляться из-за настроек пользователей, которые платформа 8.3 запоминает. К примеру, если у какого-то пользователя при открытии списка документов стоял отбор по реквизиту, который в обновлении был удален, программа выдаст ошибку при попытке открыть список документов. Еще один симптом того, что проблема именно в настройках пользователей, если один пользователь выполняет действие без проблем, а у другого вылетает ошибка. Исправить ее можно, очистив настройки пользователей. Для этого нужно открыть меню Администрирование-Настройки пользователей и прав.

Затем нужно открыть подменю «Персональные настройки пользователей» и выбрать пункт «Очистка настроек».

Здесь можно выбрать – очистить ли настройки всех пользователей или нескольких. Также можно выбрать конкретную настройку или очистить все настройки (очень удобно, если знаете, у какого пользователя и в каком месте вылетает ошибка).

4). Ошибка разработчиков

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

Можно подождать следующего обновления или «обновиться» на чуть более старый релиз программы. Как правило, совсем уж явные ошибки разработчики исправляют быстро.

Также имеет смысл написать в техподдержку. В зависимости от того, какой используется программный продукт это может быть адрес v8@1c.ru для стандартных конфигураций фирмы 1С. Для программных продуктов других производителей адреса поддержки будут отличаться, их можно найти на официальном сайте разработчика. Если нет совершенно никакой возможности решить проблему быстро, а ошибка очень мешает работе, можно обратиться к специалисту 1С, внести изменения в типовой функционал – в этом случае нужно понимать, что при следующем обновлении эти изменения могут быть затерты и за ними нужно следить, поэтому проводить обновление должен человек, знающий, как обновлять измененные конфигурации.

Специалист компании ООО «Кодерлайн» 

Евгения Скунцева.

You will need MyType to be a union type where one member of the union requires the relevant properties, while the other member either prohibits them or makes them optional, depending on the use case.

TypeScript doesn’t have an «official» or direct syntax for prohibiting a property. Merely leaving the property out of the type definition doesn’t really have this effect, especially with unions. See Why does A | B allow a combination of both, and how can I prevent it? for more information.

Instead, you can make the property optional with a value of the impossible never type. Since you cannot find a value of the never type, an optional property of type never can only meaningfully be satisfied by not including the property at all.

I’d recommend making a base type that your union members extend.

interface BaseMyType {
  someProp: string;
  counter?: number;
  maxCount?: number;
}

If you want to allow either both maxCount and counter or neither of them to appear, then you can do it like this:

interface MyTypeWithCounter extends BaseMyType {
  counter: number,
  maxCount: number
}

interface MyTypeWithoutCounter extends BaseMyType {
  counter?: never,
  maxCount?: never;
}

type MyType = MyTypeWithCounter | MyTypeWithoutCounter

And test it:

let myType: MyType;
myType = { someProp: "abc", counter: 123, maxCount: 456 }; // okay
myType = { someProp: "abc", maxCount: 456 }; // error
myType = { someProp: "abc", counter: 123, }; // error
myType = { someProp: "abc", }; // okay

On the other hand, if you just want to make sure that counter appears if maxCount does, and otherwise counter should be allowed but not required, then you can write it this way:

interface MyTypeWithMaxCount extends BaseMyType {
  counter: number,
  maxCount: number
}

interface MyTypeWithoutMaxCount extends BaseMyType {
  maxCount?: never;
}

type MyType = MyTypeWithMaxCount | MyTypeWithoutMaxCount

And test it:

let myType: MyType;
myType = { someProp: "abc", counter: 123, maxCount: 456 }; // okay
myType = { someProp: "abc", maxCount: 456 }; // error
myType = { someProp: "abc", counter: 123, }; // okay
myType = { someProp: "abc", }; // okay

Playground link to code

Содержание
  1. Знакомство с фильтром woocommerce_checkout_fields
  2. Делаем обязательные поля не такими уж и обязательными 🙂
  3. Убираем лишние поля при оформлении заказа
  4. Меняем порядок полей
    1. Сортировка полей внутри группы
    2. Перемещение поля в другую группу
  5. Добавляем новые поля оформления заказа в WooCommerce

У WooCommerce, как и WordPress, есть куча отличных зацепок. При работе с ними нам потребуется вносить изменения всего в один файл и часто это functions.php. Этого будет достаточно, но конечно, было бы лучше, если бы это был functions.php вашей дочерней темы.

Фильтр, с которым будем работать – это woocommerce_checkout_fields.


Знакомство с фильтром woocommerce_checkout_fields

Если вы попали на эту страницу только потому, что хотите удалить некоторые ненужные поля оформления заказа в WooCommerce, то смело пропускайте этот шаг. Но если вы хотите понять весь процесс, то продолжайте планомерно поглощать информацию ?

Итак, добавьте товар в корзину на вашем сайта и перейдите на страницу оформления заказа WooCoommerce. В качестве темы используется «Storefront» и нашем случае страница оформления заказа выглядит вот так:

Поля на странице оформления заказа в WooCommerce

Поля на странице оформления заказа в WooCommerce

Давайте посмотрим, из чего состоит эта страница, а для этого вставляем следующий код в functions.php:

add_filter( 'woocommerce_checkout_fields' , 'wpbl_show_fields' );
 
function wpbl_show_fields( $array ) {
	
	// Выводим список полей, но только если пользователь имеет права админа
	if( current_user_can( 'manage_options' ) ){
	
		echo '<pre>';
		print_r( $array);
		echo '</pre>';

	}
	
	return $array;
}

После вставки кода вы увидите массив всех полей оформления заказа в WooCommerce с параметрами. Как вы можете видеть в массиве, эти поля отсортированы по группам: billing, shipping, account, order.

А конкретный массив полей, например для поля «Название компании» выглядит так:

[billing_company] => Array
	(
		[label] => Название компании
		[class] => Array
			(
				[0] => form-row-wide
			)

		[autocomplete] => organization
		[priority] => 30
		[required] => 
	)

Посмотрели на все имеющиеся поля оформления заказа и продолжаем…


Делаем обязательные поля не такими уж и обязательными 🙂

В этом руководстве мы будет работать с вариативным товарам, но существенной разницы нет.

Просто так пользователь не может завершить процедуру оформления заказа. В WooCommerce есть несколько обязательных полей по умолчанию, а выглядит валидация вот так:

Обязательные поля при оформлении заказа WooCommerce

Обязательные поля при оформлении заказа WooCommerce

В рамках этого руководства мы будем работать в основном с woocommerce_checkout_fields, но если вам одновременно нужны разные поля для выставления счета (Billing) и для доставки (Shipping), лучше использовать зацепку woocommerce_default_address_fields, потому что она влияет как на поля доставки, так и на выставление счетов одновременно.

Следующий код сделает все поля не странице оформления заказа не обязательными, ну разве что кроме поля для ввода телефона (см. чуть ниже):

add_filter( 'woocommerce_default_address_fields' , 'wpbl_fileds_validation' );
 
function wpbl_fileds_validation( $array ) {
	
	// Имя
	unset( $array['first_name']['required']);
	
	// Фамилия
	unset( $array['last_name']['required']);
	
	// Область / район
	unset( $array['state']['required']);
	
	// Почтовый индекс
	unset( $array['postcode']['required']);
	
	// Населённый пункт
	unset( $array['city']['required']);
	
	// 1-ая строка адреса 
	unset( $array['address_1']['required']);
	
	// 2-ая строка адреса 
	unset( $array['address_2']['required']);
	
	// Возвращаем обработанный массив
	return $array;
	
}

Ну а что там с полем телефона? К сожалению он не входит в массив полей адреса. Придется использовать woocommerce_checkout_fields, чтобы сделать поле не обязательным:

add_filter( 'woocommerce_checkout_fields', 'wpbl_phone_field_validation' );
 
function wpbl_phone_field_validation( $array ) {
	
	// Телефон
	unset( $array['billing']['billing_phone']['required'] );
	
	// Возвращаем обработанный массив
	return $array;
}

Убираем лишние поля при оформлении заказа

Самое плохо, что можно сделать это тупо скрыть не нужные поля используя CSS. Пожалуйста не делайте так!

Избавить от лишних полей очень просто:

add_filter( 'woocommerce_checkout_fields', 'wpbl_remove_some_fields', 9999 );
 
function wpbl_remove_some_fields( $array ) {
 
	//unset( $array['billing']['billing_first_name'] ); // Имя
	//unset( $array['billing']['billing_last_name'] ); // Фамилия
	//unset( $array['billing']['billing_email'] ); // Email
	//unset( $array['order']['order_comments'] ); // Примечание к заказу
 
	unset( $array['billing']['billing_phone'] ); // Телефон
	unset( $array['billing']['billing_company'] ); // Компания
	unset( $array['billing']['billing_country'] ); // Страна
	unset( $array['billing']['billing_address_1'] ); // 1-ая строка адреса 
	unset( $array['billing']['billing_address_2'] ); // 2-ая строка адреса 
	unset( $array['billing']['billing_city'] ); // Населённый пункт
	unset( $array['billing']['billing_state'] ); // Область / район
	unset( $array['billing']['billing_postcode'] ); // Почтовый индекс
 	
	// Возвращаем обработанный массив
	return $array;
}

Приоритет 9999 для зацепки выбран не случайно. Такого рода изменения нужно запускать как можно позже. Кто знает, что там у вас в теме?

Конечно, если удалить платежные данные для оформления заказа, то не стоит наедятся, что оплата картой будет работать. Конечно, нет. Но если вы используете другие методы оплаты, то все должно быть хорошо.

Первые четыре строчки закомментированы, так как в качестве примера мы оставляем Имя, Фамилия, Email и Примечание к заказу:

Убираем лишние поля при оформлении заказа WooCommerce

Убираем лишние поля при оформлении заказа WooCommerce

Меняем порядок полей

Сортировка полей может показаться одной из самых муторных процедур, да собственно так и есть, но пропустить это важный пункт ни как нельзя.

Сортировка полей внутри группы

Во-первых, вы должны помнить, что поля разделены на группы, а их всего 4:

  • billing – Адрес выставления счёта
  • shipping – Адрес доставки
  • account – Информация об аккаунте
  • order – Детали заказа

Каждая из этих групп содержит поля и можно легко изменить их порядок с помощью специального параметра приоритета.

В качестве примера давайте сделаем поле Email первым, а это всего пара строк кода:

add_filter( 'woocommerce_checkout_fields', 'wplb_email_first' );
 
function wplb_email_first( $array ) {
	
	// Меняем приоритет
	$array['billing']['billing_email']['priority'] = 4;
	
	// Возвращаем обработанный массив
	return $array;
}

А в результате страница оформления заказа будет выглядеть вот так:

Меняем приоритет поля оформления заказа в WooCommerce

Меняем приоритет поля оформления заказа в WooCommerce

Почему мы установили priority (приоритет) равный 4? Всё просто. Каждое из полей по умолчанию имеет свой приоритет, все они перечислены в таблице ниже. Итак, согласно таблице, чтобы сделать поле электронной почты первым, нужно использовать значение меньше 10.

Группа Название Приоритет
Billing billing_first_name 10
billing_last_name 20
billing_company 30
billing_country 40
billing_address_1 50
billing_address_2 60
billing_city 70
billing_state 80
billing_postcode 90
billing_phone 100
billing_email 110
Shipping shipping_first_name 10
shipping_last_name 20
shipping_company 30
shipping_country 40
shipping_address_1 50
shipping_address_2 60
shipping_city 70
shipping_state 80
shipping_postcode 90
Account account_password
Order order_comments

Иногда после игр с приоритетами можно поломать верстку и получится что-то вроде этого:

Поля при оформлении заказа отображаются не корректно

Поля при оформлении заказа отображаются не корректно

Почему так происходит? А всё просто – недостаточно отсортировать массив полей. Необходимо применить соответствующие классы и к каждому полю.

На самом деле каждое поле оформления заказа имеет свой стиль (класс CSS), в зависимости от его положения, есть 3 основных класса:

  • form-row-first – 50% в ширину, первый,
  • form-row-last – 50% в ширину, второй,
  • form-row-wide – 100% в ширину.

Давайте расставим правильные приоритеты и назначим плавильные CSS классы:

add_filter( 'woocommerce_checkout_fields', 'wplb_reorder', 9999 );
 
function wplb_reorder( $array ) {
	
	// Меняем приоритет
	$array['billing']['billing_email']['priority'] = 30;
	$array['billing']['billing_phone']['priority'] = 40;
	
	// Назначаем CSS классы
	$array['billing']['billing_email']['class'][0] = 'form-row-first';
	$array['billing']['billing_phone']['class'][0] = 'form-row-last';
	
	// Возвращаем обработанный массив
	return $array;
}

И как результат – всё выглядит правильно и приятно:

Правильные приоритеты и CSS классы для полей оформления заказа

Правильные приоритеты и CSS классы для полей оформления заказа

Всё просто да? 🙂

Перемещение поля в другую группу

К сожалению этот метод не всегда работает, да и не со всеми полями, но и обойти его стороной тоже нельзя. Для примера давайте переместим поле Email другую группу:

add_filter( 'woocommerce_checkout_fields', 'wpbl_move_to_order_group', 10000 );
 
function wpbl_move_to_order_group( $array ){
 
	// 1. Добавляем поле в новую группу
	$array['order']['billing_email'] = $array['billing']['billing_email'];
 
	// 2. Удаляем поле из предыдущей группы
	unset( $array['billing']['billing_email'] );
	
	// 3. Возвращаем полям прежний CSS классы (не нужно если до этого не меняли)
	$array['order']['billing_email']['class'][0] = 'form-row-wide';
	$array['billing']['billing_phone']['class'][0] = 'form-row-wide';
 
	// Возвращаем обработанный массив
	return $array;
 
}

И как результат:

Перемещение поля из одной группы в другую

Перемещение поля из одной группы в другую

В качестве примера давайте добавим два поля в форму оформления заказа WooCommerce – выпадающий список под деталями выставления счета и флажок «Подписаться» в разделе примечаний к заказу. Первое поле будет обязательным.

Прежде всего, нам надо решить где разместить наши новые поля, а вот из чего нужно сделать выбор:

  • woocommerce_before_checkout_billing_form – До формы адреса оплаты.
  • woocommerce_after_checkout_billing_form – После формы адреса оплаты.
  • woocommerce_before_checkout_registration_form – До формы регистрации.
  • woocommerce_after_checkout_registration_form – После формы регистрации.
  • woocommerce_before_checkout_shipping_form – До формы адреса доставки.
  • woocommerce_after_checkout_shipping_form – После формы адреса доставки.
  • woocommerce_before_order_notes – До примечания к заказу.
  • woocommerce_after_order_notes – После примечания к заказу.

Всё понятно из названий зацепок, ими мы воспользуемся ниже, но они могут не сработать только в одном случае – если шаблоны оформления заказа WooCommerce по умолчанию: form-shipping.php и form-billing.php были переопределены в теме. В этом случае придется вручную добавлять новые поля в файлы темы в каталоге /woocommerce/checkout.

Итак, вот собственно код:

// Добавляем поля
add_action( 'woocommerce_after_checkout_billing_form', 'wpbl_select_field' );
add_action( 'woocommerce_after_order_notes', 'wpbl_checkbox_filed' );
 
// Сохраняем поля
add_action( 'woocommerce_checkout_update_order_meta', 'wpbl_save_fields' );
 
// Поле select
function wpbl_select_field( $checkout ){
 
	// Описываем поле
	woocommerce_form_field( 'dron', array(
		'type'          => 'select', // Тип поля. Можно любое - text, textarea, select, radio, checkbox, password. В нашем случае это select
		'required'	=> true, // этот параметр добавляет звездочку "*" к полю
		'class'         => array('wpbl-field', 'form-row-wide'), // Массив CSS классов
		'label'         => 'Доставить договор дроном?', // Заголовок поля
		'label_class'   => 'wpbl-label', // CSS класс заголовка
		'options'	=> array( // Массив опций для типа "select" или "radio"
			''		=> 'Что-то нужно выбрать', // Пусто значение означает, что нужно что-то выбрать
			'Yes'	=> 'Да, я хочу увидеть дрона!', // 'value'=>'Name'
			'No'	=> 'Нет, я сам к вам приду'
			)
		), $checkout->get_value( 'dron' ) );
 
	// Сюда так же можно добавить чуть-чуть HTML кода например <hr> и что-то ещё.
	// В качестве примера мы добавляем стилевое оформление для выпадающего списка. Не далейте так. Все стили должны быть в CSS файле!
	echo '<style>#dron{padding:15px; background:#f1f1f1; border:none;}</style>';
 
}
 
// Поле checkbox
function wpbl_checkbox_filed( $checkout ) {
 
	woocommerce_form_field( 'subscribe', array(
		'type'	=> 'checkbox',
		'class'	=> array('wpbl-field form-row-wide'),
		'label'	=> ' Я хочу подписать на рассылку',
		), $checkout->get_value( 'subscribe' ) );
 
}
 
// Функция сохранения
function wpbl_save_fields( $order_id ){
 
	// Сохраняем select
	if( !empty( $_POST['dron'] ) ){
		update_post_meta( $order_id, 'dron', sanitize_text_field( $_POST['dron'] ) );
	}
		
	// Сохраняем checkbox
	if( !empty( $_POST['subscribe'] ) && $_POST['subscribe'] == 1 ){
		update_post_meta( $order_id, 'subscribe', 1 );
	}
		
}

И как результат:

Добавляем поля оформления заказа в WooCommerce

Добавляем поля оформления заказа в WooCommerce

А после оформления в информации о заказе (WooCommerce → Заказы) появятся новые, только что созданные поля:

Сохранение значения новых полей в ордере

Сохранение значения новых полей в ордере

К сожалении, даже с учетом того, что для нашего выпадающего списка мы поставили ‘required’ => true, поле всё еще по сути не обязательно для заполнения. 🙁

Добавив небольшой фрагмент кода мы решим эту задачку:

add_action('woocommerce_checkout_process', 'wpbl_select_field_validation');
 
function wpbl_select_field_validation() {
 
	// Можно как угодно проверять, а в нашем случае это простая проверка на наличие в $_POST[]
	if ( empty( $_POST['dron'] ) ){
		wc_add_notice( 'Дрона то отправлять или нет?.', 'error' );
	}
		
}

Посмотрите на второй параметр функции wc_add_notice – он также поддерживает типы уведомлений «success» и «notice», но параметр «error» – именно то, что нужно в нашем случае.

Вывод ошибки если пользователь не заполнил нужное нам поле при оформлении заказа

Вывод ошибки если пользователь не заполнил нужные нам поля оформления заказа в WooCommerce

На этом пока всё.

Если у вас есть вопросы или просто хотите поделиться своим мнением, то оставляйте комментарии ✌️

Спасибо.

Понравилась статья? Поделить с друзьями:
  • Ошибка в драйвере монитора как исправить
  • Ошибка в драйвере монитора для фотошопа
  • Ошибка в драйвере монитора photoshop
  • Ошибка в драйвере ntoskrnl exe
  • Ошибка в доступе отказано apb