📚 pbMessage — универсальный вывод сообщений
pbMessage — это маленький универсальный класс, который показывает успешные или ошибочные сообщения после pbFetch или любых твоих асинхронных операций. Он же отвечает за диалог подтверждения перед запросом.
✅ Зачем нужен
- Позволяет автоматически показывать сообщения из JSON-ответов
{ success: true|false, message: "..." }. - Работает по умолчанию вместе с
pbFetch— без ручного вывода. - Контролируется через кастомные события
pb:successиpb:error— ты можешь отменить автоматический показ. - Даёт одну точку, где меняется вид сообщений на всём сайте: подставил свой обработчик — и вместо текста в блоке появились тосты или модалки.
- Можно легко настроить CSS классы, куда вставлять сообщение и как его очищать.
⚙️ Как работает
🚦 Основная логика
pbMessage.success(ctx, message)
pbMessage.error(ctx, message)
pbMessage.clear(ctx)ctx— это DOM-элемент, внутри которого ищется блок для вывода. Обычно это форма или элемент изpb-target.pbMessage.success()ищет[pb-success-message], а если не нашёл —[pb-message].pbMessage.error()ищет[pb-error-message], а если не нашёл — тот же[pb-message].- Если блок не найден — ничего не происходит.
ctx обязателен, и молча
Все три метода при пустом ctx просто выходят: ни сообщения, ни ошибки в консоли. Именно так выглядит самый частый «pbMessage не работает» — сообщение искать негде. pbFetch берёт контекстом форму элемента, а если формы нет — элемент из pb-target; когда нет ни того, ни другого, ctx равен null.
🏷️ Как разметить HTML
1️⃣ Один универсальный блок
<div pb-message class="d-none"></div>2️⃣ Раздельные блоки для успеха и ошибки
<div pb-success-message class="d-none"></div>
<div pb-error-message class="d-none"></div>✔️ Рекомендуется располагать эти блоки внутри формы или внутри таргета, чтобы pbMessage точно нашёл их по контексту.
📌 Пример разметки формы
<form id="my-form">
<input type="text" name="name">
<button
type="submit"
pb-post="/api/submit"
pb-expect="json"
pb-include="#my-form input"
>
Отправить
</button>
<!-- Лучше внутри формы -->
<p pb-success-message class="text-success d-none"></p>
<p pb-error-message class="text-danger d-none"></p>
</form>Текст вставляется через innerHTML — простую разметку (<b>, <a>) сервер может прислать прямо в message. Значит и экранировать пользовательский ввод должен сервер.
🧩 Автоматическая интеграция с pbFetch
Сообщение показывается, когда сошлись три условия:
- запрос сделан с
pb-expect="json"(дляhtmlсообщений нет вообще); - в ответе есть непустое
data.message; - соответствующее событие не отменено.
// при response.ok
pbMessage.success(ctx, data.message)
// при HTTP-ошибке
pbMessage.error(ctx, data.message)Ты можешь отменить автопоказ, добавив в обработчике:
document.addEventListener('pb:success', (e) => {
e.preventDefault(); // сообщение не покажется автоматически
// твоя логика
});preventDefault() на pb:success отключает не только сообщение
На успешном ответе это событие сторожит весь разбор JSON: сообщение, редирект по data.redirect и подмену разметки из data.html. Отменяя показ сообщения, ты берёшь на себя и остальное. На pb:error отменяется только сообщение.
❓ Подтверждение действия
Атрибут pb-confirm у pbFetch вызывает pbMessage.confirmHandler(el, message) и отправляет запрос, только если тот вернул истину:
<button pb-delete="/cargo/12" pb-expect="json" pb-confirm="Удалить заказ?">
Удалить
</button>Штатный обработчик — это браузерный confirm(). Заменяется на свой так:
pbMessage.setConfirmHandler(async (el, message) => {
const result = await Swal.fire({
title: message,
icon: 'question',
showCancelButton: true,
confirmButtonText: 'Да, удалить'
});
return result.isConfirmed;
});Обработчик может быть async — его дождутся. Он должен вернуть true, чтобы запрос ушёл; исключение внутри обработчика отменяет запрос и пишется в консоль.
🎨 Настройка классов через конфиг и системные настройки
По умолчанию классы для сообщений подставляются из системных настроек:
pageblocks_msg_success— классы для успешного сообщенияpageblocks_msg_error— классы для ошибокpageblocks_hidden_class— класс, который скрывает блок сообщений (например,d-none)
Пример значений из настроек:
pageblocks_msg_success = "text-success"
pageblocks_msg_error = "text-danger,text-error"
pageblocks_hidden_class = "d-none"Подставляет их не сам файл pb.message.v300.js, а компонент: событие OnWebPageInit при включённой настройке pageblocks_load_scripts дописывает на страницу вызов setConfig() с этими значениями. В самом классе прошиты только запасные значения:
pbMessage.config = {
successClasses: ['text-success'],
errorClasses: ['text-error', 'text-danger'],
hiddenClass: 'd-none'
};Классы — Bootstrap-овские; своих стилей PageBlocks для них не поставляет. На теме без Bootstrap задайте в настройках собственные.
Можно вручную переопределить через setConfig():
pbMessage.setConfig({
successClasses: ['alert', 'alert-success'],
errorClasses: ['alert', 'alert-danger'],
hiddenClass: 'hidden' // например, TailwindCSS класс
});Показывая сообщение, pbMessage снимает класс скрытия и классы противоположного типа, а затем вешает нужные. Поэтому один блок [pb-message] спокойно переключается с ошибки на успех и обратно.
🧹 Очистка сообщений
Если нужно убрать сообщение и сбросить классы:
pbMessage.clear(form);
// или pbMessage.clear(targetElement);Метод проходит по всем трём атрибутам — [pb-success-message], [pb-error-message], [pb-message], — очищает текст, возвращает класс скрытия и снимает классы успеха и ошибки.
🔥 Полный API
| Метод | Описание |
|---|---|
pbMessage.success(ctx, message) | Показать успешное сообщение |
pbMessage.error(ctx, message) | Показать ошибку |
pbMessage.clear(ctx) | Очистить все сообщения и сбросить добавленные классы |
pbMessage.setSuccessHandler(fn) | Переопределить обработчик для успеха |
pbMessage.setErrorHandler(fn) | Переопределить обработчик для ошибок |
pbMessage.setConfirmHandler(fn) | Переопределить диалог подтверждения (pb-confirm) |
pbMessage.setConfig({...}) | Задать CSS классы для успеха/ошибки (массивы классов) |
Все три set*Handler() бросают TypeError, если передать не функцию.
✔️ Пример с использованием SweetAlert2
pbMessage.setSuccessHandler((ctx, message) => {
Swal.fire({
icon: 'success',
title: 'Успех!',
text: message
});
});
pbMessage.setErrorHandler((ctx, message) => {
Swal.fire({
icon: 'error',
title: 'Ошибка!',
text: message
});
});Свой обработчик волен не смотреть на ctx вовсе — тосты и модалки живут поверх страницы, и тогда исчезает проблема «блока для сообщения нет в контексте».