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.
Модификаторы:
<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[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/