Spec-Zone.ru › htmx

hx-on

Выполняет встроенный JavaScript при возникновении события

Атрибут hx-on связывает встроенный JavaScript с событием, при возникновении которого он будет выполнен.

Это улучшенная версия свойств onevent, которая сохраняет поведение в разметке (Локальность поведения).

Синтаксис

Простая форма

Одно событие, одно выражение:

<!-- hx-on:<event>=<js> -->

<dialog hx-on:load="this.showModal()">

Для событий htmx используйте :: как сокращение для htmx::

<!-- hx-on::before:request is shorthand for hx-on:htmx:before:request -->
<button hx-get="/api" hx-on::before:request="showSpinner()">
<button hx-get="/api" hx-on::after:request="hideSpinner()">

Расширенная форма

Основана на грамматике hx-trigger и добавляет -> для связывания событий с JavaScript:

<!-- hx-on="<event>[<filter>] <modifiers> [, ...] -> <js> | { <js>; ... } [; ...]" -->

<!-- Open dialog on page load / swap -->
<dialog hx-on="load -> this.showModal()">

<!-- Unfocus input on Escape -->
<input hx-on="keydown[key=='Escape'] -> this.blur()">
    
<!-- Close dialog on custom event (e.g. HX-Trigger: closeDialog) -->
<dialog hx-on="closeDialog from:body -> this.close()">
    
<!-- Close on backdrop click OR custom event -->
<dialog hx-on="click from:self, closeDialog from:body -> this.close()">

<!-- Run multiple statements -->
<dialog hx-on="close -> this.remove(); log('dialog removed')">
        
<!-- Different code for different events -->
<dialog hx-on="load -> this.showModal();
               click from:self, closeDialog from:body -> this.close();
               close -> this.remove(); log('removed')">
  • событие или события -> слева, код JavaScript справа
  • , несколько событий с одним и тем же кодом
  • ; отдельные пары «событие → код» (разделение выполняется только по ; непосредственно перед ->, поэтому точки с запятой в коде JS не помешают)

Стандартные события

hx-on работает с любыми событиями DOM: click, input, keyup, submit и другими.

<button hx-on:click="...">
<input hx-on:input="...">
<form hx-on:submit="...">
<div hx-on:mouseenter="...">

Пользовательские события

Поддерживаются и пользовательские события. Отправляйте их из JavaScript с помощью htmx.trigger() или с сервера через заголовок ответа HX-Trigger.

События из HX-Trigger отправляются на body, поэтому для прослушивания используйте from:body:

<div hx-on="productsUpdated from:body -> log('Products updated!')">

Синтетические события

htmx предоставляет синтетические события помимо стандартных событий DOM.

Они работают как с простой формой (hx-on:load), так и с расширенной (hx-on="load -> ...").

load

Возникает, когда элемент загружается в DOM.

<div hx-on:load="this.classList.add('loaded')">

revealed

Возникает, когда элемент прокручивается в область просмотра.

<div hx-on:revealed="this.classList.add('visible')">

Примечание: revealed всегда отслеживает область просмотра браузера. Для прокручиваемых контейнеров с overflow вместо этого используйте intersect с root.

intersect

Возникает, когда элемент становится видимым в области просмотра.

Использует API IntersectionObserver.

Модификаторы:

  • root
  • rootMargin
  • threshold
<div hx-on="intersect once -> this.classList.add('in-view')">
<div hx-on="intersect rootMargin:100px -> this.classList.add('near')">

every <time>

Возникает многократно с заданным интервалом. Доступно только в расширенной форме.

<div hx-on="every 1s -> this.textContent = new Date().toLocaleTimeString()">

Модификаторы событий

[filter]

Выражение JavaScript в квадратных скобках после имени события. Событие срабатывает, только если выражение возвращает true.

<button hx-on="click[ctrlKey] -> navigator.clipboard.writeText(this.textContent)">

Внутри скобок все свойства события доступны по имени без префикса:

  • click → altKey, ctrlKey, shiftKey, metaKey, …
  • keydown → key, code, repeat, …

Глобальные функции также доступны: click[hasUnsavedChanges()].

once

Срабатывает один раз, затем перестаёт прослушивать событие.

<button hx-on="click once -> this.textContent = 'Done!'">Click me</button>

changed

Срабатывает, только если value элемента изменился с прошлого раза.

<input hx-on="input changed -> console.log(this.value)">

Примечание: change — это событие DOM. changed — модификатор htmx. Это разные вещи.

delay:<time>

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

<input hx-on="input delay:500ms -> console.log(this.value)">

throttle:<time>

Срабатывает, а затем игнорирует последующие события в течение заданного интервала.

<div hx-on="scroll throttle:100ms -> this.dataset.scrollY = window.scrollY"></div>

from:<selector>

Прослушивает события на другом элементе. Принимает CSS-селектор или расширенный селектор. Есть два специальных значения: self (только сам элемент, без дочерних элементов) и outside (любой элемент за пределами данного элемента).

<div hx-on="keydown[key=='Escape'] from:body -> this.hidden = true">
<div hx-on="click from:outside -> this.hidden = true">

target:<selector>

Срабатывает, только если event.target соответствует заданному CSS-селектору.

<ul hx-on="click target:li -> event.target.classList.toggle('selected')"></ul>

prevent

Вызывает event.preventDefault().

<form hx-on="submit prevent -> console.log(new FormData(this))"></form>

stop / consume

Вызывает event.stopPropagation().

<button hx-on="click stop -> this.textContent = 'clicked'"></button>

halt

Сокращение для prevent stop.

<a hx-on="click halt -> console.log(this.href)"></a>

capture

Прослушивает событие на фазе захвата (сверху вниз), а не на фазе всплытия (снизу вверх).

<div hx-on="click capture -> console.log('capture:', event.target.tagName)"></div>

passive

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

<div hx-on="scroll passive -> this.dataset.scrollY = window.scrollY"></div>

Символы

Как и в onevent, в скриптах обработчиков событий доступны два символа:

this

Элемент, на котором установлен атрибут hx-on.

<button hx-on:click="this.classList.toggle('active')">Toggle</button>

event

Событие, которое произошло.

Все свойства event.detail становятся доступными в области видимости, поэтому можно написать message вместо event.detail.message:

<!-- dispatched with detail: { message: 'hello' } -->
<div hx-on="my-event -> alert(message)">
<!-- equivalent to: alert(event.detail.message) -->
</div>

Примечания

  • Работает с любыми событиями, включая события htmx.
  • hx-on не наследуется, но события дочерних элементов всё равно всплывают и вызывают его.
  • Обе формы (hx-on:event и hx-on="...") могут использоваться одновременно на одном элементе.
  • Браузеры преобразуют имена атрибутов в нижний регистр, поэтому hx-on:myEvent не будет соответствовать отправке события myEvent. Используйте расширенную форму: hx-on="myEvent -> ...".

Асинхронный код

Используйте await верхнего уровня в hx-on. Не добавляйте асинхронную обёртку.

<!-- Good: htmx handles errors -->
<button hx-on:click="await save()">Save</button>

<!-- Bad: errors go unhandled -->
<button hx-on:click="(async () => { await save() })()">Save</button>

См. также

  • hx-trigger (атрибут)
  • Скрипты на стороне клиента (руководство)
  • Расширенные селекторы (справочник)
  • Локальность поведения (эссе)

Licensed under the Zero-Clause BSD License.
https://four.htmx.org/reference/attributes/hx-on/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API