Ни для кого не секрет, что онлайн-формы могут стать серьёзным испытанием для пользователей. Особенно когда они выглядят как список полей для ввода без каких-либо подсказок. Однако мы, как разработчики, можем значительно облегчить жизнь посетителям наших сайтов.
Используем CSS
В CSS существует четыре специальных псевдокласса, применимых к полям формы: :valid
(валидное поле), :invalid
(невалидное), :required
(обязательное) и :optional
(необязательное). Их можно использовать, чтобы добавлять некоторые — хотя и весьма ограниченные — подсказки пользователям, заполняющим форму.
Используя :valid
и :invalid
, мы можем показать пользователю, правильно ли заполнено поле по мере ввода.
input:valid {
border-color: green;
}
input:invalid {
border-color: red;
}
Однако с этим способом связана одна проблема: стили применяются до того, как пользователь начнёт работу с формой. Поля, обязательные для заполнения, сразу подсветятся нам как Стилизация состояний JavaScript даёт намного больше возможностей для улучшения работы пользователей с формами. Давайте рассмотрим в качестве примера три числовых поля, у каждого из которых установлен минимум в 10, максимум в 100 и шаг в 10 единиц. Устанавливая атрибуты В результате всё, что получит пользователь — это сообщение об ошибке для первого поля. Кроме того, в этом сообщении будет указано лишь одно несоответствие из двух требуемых. Такое поведение можно исправить, изменяя показываемые валидатором сообщения. Валидируя поля, браузер проверяет их по определённому списку потенциальных ошибок. В каждом поле содержится специальный объект Примечание переводчика: Слово «mismatch» переводится как «несоответствие». Поэтому в значениях По умолчанию браузер отобразит лишь одну ошибку. Что мы можем сделать, так это проверить все эти значения самостоятельно и, если найдутся ошибки, сохранить их. Как только мы сохраним все ошибки для одного поля, мы можем отобразить весь их список в виде специального сообщения об ошибке при помощи функции Теперь при попытке отправить форму мы увидим вот это: Отображаем несколько ошибок в одном тултипе Стало лучше, поскольку теперь будут показываться все сообщения об ошибках, связанные с конкретным полем. Однако другая проблема всё ещё не решена: ошибки по-прежнему показываются лишь для первого поля. Это ограничение валидации, устанавливаемое браузером. Чтобы его побороть, нам нужно пойти другим путём. Вместо того, чтобы использовать встроенный тултип, мы можем добавлять сообщения об ошибках напрямую в DOM. Таким образом, все ошибки будут выводиться рядом с соответствующим полем. Этого можно добиться какой-то парой дополнительных строчек в нашем коде: Вот что происходит при клике на submit теперь: Иногда встроенной в браузер валидации бывает недостаточно. Нам может понадобиться, чтобы вводимые данные удовлетворяли некоторым дополнительным правилам. Например, чтобы в текстовом поле требовалось указать особые символы. Так как мы уже проверяем все возможные ошибки вручную в нашей функции Хотя текущий способ выглядит намного лучше, он тоже не без изъянов. Наихудший из недочётов заключается в том, что пользователь не сможет увидеть никаких сообщений, пока не нажмёт на кнопку отправки формы. Было бы гораздо лучше, если бы валидация поля происходила сразу же при его заполнении. Можно выделить три правила для того, чтобы с формой было удобно работать: Если вы хотите попробовать свои силы (и даже сделать получше), вы можете воспользоваться вот этим шаблоном.:invalid
, а необязательные — как :valid
. Это значит, что пользователь, даже не приступив к заполнению формы, может сразу же получить негативную обратную связь. Не очень-то хорошо.:required
и :optional
сама по себе не особо полезна, поскольку эта информация обычно указывается в подписях к полям формы. Однако мы можем объединить эти состояния с псевдоклассами :valid
/ :invalid
и стилизовать их комбинации. Например, мы хотим показывать лишь положительный результат, когда валидно обязательное к заполнению поле.input:required:valid {
border-color: green;
}
Используем JavaScript
<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>
min
, max
и step
, мы можем быть уверены в правильности значения только тогда, когда пользователь использует специальные контролы числового поля. Но что мешает пользователю ввести вручную некорректные данные? Вот что произойдёт, если он вставит 1
, 12
и 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 // Отсутствует обязательное значение
};
patternMismatch
, stepMismatch
и 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
} // закончился цикл
});
Показываем все ошибки для всех полей
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();
}
});
Используем нестандартные проверки валидности
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. Ошибка «Поле объекта не обнаружено» в 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
Содержание
- Знакомство с фильтром woocommerce_checkout_fields
- Делаем обязательные поля не такими уж и обязательными 🙂
- Убираем лишние поля при оформлении заказа
- Меняем порядок полей
- Сортировка полей внутри группы
- Перемещение поля в другую группу
- Добавляем новые поля оформления заказа в WooCommerce
У WooCommerce, как и WordPress, есть куча отличных зацепок. При работе с ними нам потребуется вносить изменения всего в один файл и часто это functions.php. Этого будет достаточно, но конечно, было бы лучше, если бы это был functions.php вашей дочерней темы.
Фильтр, с которым будем работать – это woocommerce_checkout_fields.
Знакомство с фильтром woocommerce_checkout_fields
Если вы попали на эту страницу только потому, что хотите удалить некоторые ненужные поля оформления заказа в WooCommerce, то смело пропускайте этот шаг. Но если вы хотите понять весь процесс, то продолжайте планомерно поглощать информацию ?
Итак, добавьте товар в корзину на вашем сайта и перейдите на страницу оформления заказа WooCoommerce. В качестве темы используется «Storefront» и нашем случае страница оформления заказа выглядит вот так:
Давайте посмотрим, из чего состоит эта страница, а для этого вставляем следующий код в 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_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 и Примечание к заказу:
Меняем порядок полей
Сортировка полей может показаться одной из самых муторных процедур, да собственно так и есть, но пропустить это важный пункт ни как нельзя.
Сортировка полей внутри группы
Во-первых, вы должны помнить, что поля разделены на группы, а их всего 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; }
А в результате страница оформления заказа будет выглядеть вот так:
Почему мы установили 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; }
И как результат – всё выглядит правильно и приятно:
Всё просто да? 🙂
Перемещение поля в другую группу
К сожалению этот метод не всегда работает, да и не со всеми полями, но и обойти его стороной тоже нельзя. Для примера давайте переместим поле 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 → Заказы) появятся новые, только что созданные поля:
К сожалении, даже с учетом того, что для нашего выпадающего списка мы поставили ‘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» – именно то, что нужно в нашем случае.
На этом пока всё.
Если у вас есть вопросы или просто хотите поделиться своим мнением, то оставляйте комментарии ✌️
Спасибо.