Skip to content

🚀 pbFetch: асинхронные запросы через HTML-атрибуты

pbFetch — это нативный JavaScript-класс для работы с AJAX-запросами, вдохновлённый подходом HTMX, но с собственным неймспейсом pb-. Реализует отправку GET, POST, PUT, PATCH и DELETE-запросов без перезагрузки страницы и позволяет динамически обновлять контент через декларативные атрибуты.

🔗 Подключение

  1. Включите настройку pageblocks_load_scripts, чтобы скрипт подключился автоматически.
  2. Или подключите вручную:
html
<script src="/assets/components/pageblocks/js/web/pb.fetch.v280.js"></script>
<script>
  pbFetch.init();
</script>

⚡️ Основные возможности

  • Асинхронная загрузка HTML или JSON-ответов.
  • Обновление контента через pb-target и pb-swap.
  • Автоматический показ сообщений через pbMessage.
  • Поддержка индикаторов загрузки.
  • Обработка событий каждого этапа.
  • Поддержка множественных событий в pb-trigger.
  • Поддержка автоматической загрузки при pb-trigger="load".

🗂️ Базовые атрибуты

АтрибутОписание
pb-getОтправка GET-запроса.
pb-postОтправка POST-запроса.
pb-putОтправка PUT-запроса.
pb-patchОтправка PATCH-запроса.
pb-deleteОтправка DELETE-запроса.
pb-pathАльтернативный способ указания URL.
pb-targetCSS-селектор элемента, куда будет вставлен ответ.
pb-swapМетод вставки: innerHTML, beforeend, afterbegin, beforebegin, afterend, outerHTML. Особые значения: active, inactive, delete, hide
pb-expectФормат ожидаемого ответа: html (по умолчанию) или json.
pb-triggerСобытия, которые запускают запрос: click, submit, change, load (можно указать несколько через запятую).
pb-valsJSON-строка с данными для тела запроса.
pb-includeCSS-селектор полей формы, которые нужно включить в запрос.
pb-indicatorCSS-селектор индикатора загрузки.

🔸 HTML (pb-expect="html")

1. innerHTML (по умолчанию)

Заменяет содержимое целевого элемента.

html
<div id="box">Старый контент</div>

<button pb-trigger="click" 
        pb-url="/get/new-content" 
        pb-target="#box" 
        pb-expect="html" 
        pb-swap="innerHTML">
    Заменить контент
</button>

➡ После запроса внутри #box появится новый HTML, старый будет удалён.

2. outerHTML

Полностью заменяет сам элемент вместе с его тегом.

html
<div id="box">Контент</div>

<button pb-trigger="click" 
        pb-url="/get/full-box" 
        pb-target="#box" 
        pb-expect="html" 
        pb-swap="outerHTML">
    Заменить элемент
</button>

#box будет заменён целиком (вместе с <div>).

3. beforebegin

Вставляет HTML перед элементом.

html
<div id="item">Пункт</div>

<button pb-trigger="click" 
        pb-url="/get/row" 
        pb-target="#item" 
        pb-expect="html" 
        pb-swap="beforebegin">
    Вставить перед элементом
</button>

➡ Новый HTML будет вставлен перед #item, сам #item не изменится.

4. afterend

Вставляет HTML после элемента.

html
<div id="item">Пункт</div>

<button pb-trigger="click" 
        pb-url="/get/row" 
        pb-target="#item" 
        pb-expect="html" 
        pb-swap="afterend">
	Вставить после элемента
</button>

➡ Новый HTML будет вставлен сразу после #item.

5. beforeend

Добавляет HTML в конец содержимого элемента.

html
<ul id="list">
  <li>Пункт 1</li>
</ul>

<button pb-trigger="click" 
        pb-url="/get/item" 
        pb-target="#list" 
        pb-expect="html" 
        pb-swap="beforeend">
    Добавить элемент
</button>

➡ Новый элемент добавится в конец списка (<li> после Пункт 1).

6. afterbegin

Добавляет HTML в начало содержимого элемента.

html
<ul id="list">
  <li>Пункт 1</li>
</ul>

<button pb-trigger="click" 
        pb-url="/get/item" 
        pb-target="#list" 
        pb-expect="html" 
        pb-swap="afterbegin">
    Добавить элемент
</button>

➡ Новый элемент появится в начале списка, перед Пункт 1.

{ } JSON (pb-expect="json")

Если указано pb-expect="json", то:

  • Сервер должен вернуть JSON.
  • Данные не вставляются напрямую в DOM (как при html).
  • Они могут обрабатываться через pb-swap.

1. Динамические параметры в URL

В URL можно использовать плейсхолдеры:

  • {value} → текущее значение элемента (el.value)
  • {id} → атрибут id элемента
  • {name} → атрибут name элемента

Пример:

html
<select id="country"
        name="country"
        class="form-select"
        pb-get="/api/cities/{value}"
        pb-trigger="change"
        pb-expect="json"
        pb-target="#city">
  <option value="" selected disabled>Выберите страну</option>
</select>

➡ При выборе страны с id=2 отправится запрос /api/cities/2.

2. pb-swap="delete"

Удаляет элемент из DOM после успешного ответа.

html
<button type="button"
        pb-delete="/cargo/{id}"
        pb-expect="json"
        pb-target="#order-123"
        pb-swap="delete"
        id="123"
        class="btn-control">
  Удалить заказ
</button>

➡ Отправляется DELETE /cargo/123, при успехе — удаляется #order-123.

3. pb-swap="active"

Добавляет класс active к элементу.

html
<button type="button"
        pb-patch="/user/{id}/activate"
        pb-expect="json"
        pb-target="#user-123"
        pb-swap="active"
        id="123">
  Активировать
</button>

➡ После ответа JSON к #user-123 добавляется класс active.

4. pb-swap="inactive"

Удаляет класс active.

html
<button type="button"
        pb-patch="/user/{id}/deactivate"
        pb-expect="json"
        pb-target="#user-123"
        pb-swap="inactive"
        id="123">
  Деактивировать
</button>

➡ После ответа JSON у #user-123 убирается класс active.

5. pb-swap="hide"

Скрывает элемент (display: none).

html
<button type="button"
        pb-post="/notifications/read/{id}"
        pb-expect="json"
        pb-target="#notif-55"
        pb-swap="hide"
        id="55">
  Отметить прочитанным
</button>

➡ После ответа JSON #notif-55 будет скрыт.

⚙️ Использование в JavaScript

Методы

js
pbFetch.get(options)
pbFetch.post(options)
pbFetch.put(options)
pbFetch.patch(options)
pbFetch.delete(options)

Примеры

js
// Простой GET-запрос
pbFetch.get({
  url: '/news',
  target: '#news-block',
  swap: 'beforeend'
});

// POST-запрос с телом
pbFetch.post({
  url: '/send',
  body: new URLSearchParams({ name: 'John' }),
  expect: 'json'
});

// PUT-запрос с JSON
pbFetch.put({
  url: '/user/5',
  body: JSON.stringify({ name: 'Alice' }),
  headers: { 'Content-Type': 'application/json' },
  expect: 'json'
});

// PATCH-запрос
pbFetch.patch({
  url: '/profile',
  body: new FormData(document.querySelector('#profile-form')),
  success: (res, el) => console.log('Обновлено:', res),
  after: () => console.log('Запрос завершён')
});

// DELETE-запрос
pbFetch.delete({
  url: '/item/12',
  expect: 'json',
  success: (res) => alert('Удалено'),
  error: (err) => alert('Ошибка удаления')
});

// Отправка формы
const form = document.querySelector('#form');
pbFetch.post({
  url: form.action,
  form,
  expect: 'json'
});

// Отмена предыдущих запросов
pbFetch.get({
  url: '/search?q=test',
  cancelKey: '/search',
  cancelPrevious: true
});

Поддерживаемые опции

ОпцияОписание
methodHTTP-метод (GET, POST, PUT, PATCH, DELETE).
urlАдрес запроса.
targetСелектор для вставки HTML.
swapМетод вставки (innerHTML, beforeend, и т.п.).
expectФормат ответа: html или json.
bodyТело запроса (например, URLSearchParams, FormData, JSON).
headersКастомные заголовки.
formЭлемент формы (HTMLFormElement).
showProgressПоказывать ли события progress:start/end.
cancelKeyКлюч запроса для отмены. По умолчанию — URL без query-параметров.
cancelPreviousОтменить предыдущий запрос с тем же ключом.
beforeКолбэк перед запросом. Возвращаемое false отменяет отправку.
successКолбэк при успешном ответе.
errorКолбэк при ошибке.
afterКолбэк после завершения запроса (в любом случае).

🗨️ События

СобытиеКогда срабатывает
pb:beforeДо отправки. Можно отменить.
pb:responseПосле получения ответа, до его обработки.
pb:successПосле успешного ответа. Можно отменить показ pbMessage.
pb:errorПосле ошибки. Можно отменить показ pbMessage.
pb:progress:startПри старте загрузки (если showProgress).
pb:progress:endПосле завершения загрузки (если showProgress).
pb:afterПосле завершения запроса (в любом случае).
pb:abortЕсли запрос отменён.
pb:failПри сетевой ошибке (например, нет связи с сервером).

Пример

js
document.addEventListener('pb:success', (e) => {
  console.log('Успех:', e.detail);
});

document.addEventListener('pb:error', (e) => {
  console.log('Ошибка:', e.detail);
  e.preventDefault(); // отменить автоматический показ pbMessage
});

✅ Автоматический pbMessage

Если expect="json" и сервер возвращает { message: '...' }, pbFetch вызовет pbMessage.success() или pbMessage.error(). Для отмены этого поведения используйте preventDefault() в pb:success или pb:error.

🏆 Преимущества

  • Чистый JS-код без зависимостей.
  • Простота — работает «из коробки».
  • Поддержка загрузки по load, множественных событий.
  • Контроль и гибкость через события и JS-интерфейс.
  • Поддержка форм, индикаторов и отмены запросов.

🟢 Заключение

pbFetch — лёгкий и мощный способ внедрения асинхронных запросов в PageBlocks. Всё на чистом HTML и JavaScript. Без зависимостей, с полной управляемостью и расширяемостью.

© PageBlocks 2019-present