bigskysoftware / bigskysoftware/htmx

Feature Request: `hx-live`: Support Boolean Attribute Binding (`:?attr` / `hx-live:?attr`) for Custom Attributes & Web Components

Open
#4,019 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
49.4k
Forks
1.7k
Avg merge
3d 22h
Merged PRs (30d)
30

Description

#### Summary
Add an explicit boolean attribute binding modifier—`:?` (and its long form `hx-live:?`)—to `hx-live`.

While `hx-live` handles standard native boolean attributes (such as `disabled` or `required`) based on truthiness, generic attributes always write their stringified value (e.g., `:my-flag="false"` becomes `my-flag="false"`). This breaks Custom Elements, Web Components (like Lit's `@property({ type: Boolean })`), and dynamic state attributes (`selected`, `checked`) where DOM attribute *presence* dictates state rather than string value.

Borrowing Lit's established `?` prefix syntax, `:?` ensures that truthy values set/keep the attribute, while falsy values (including empty strings and the string `"false"`) remove the attribute entirely via native `toggleAttribute()`.

---

#### Problem & Motivation
Under the current `hx-live` attribute writing rules:
1. **Known Booleans:** Predefined native attributes like `disabled` or `required` toggle correctly.
2. **Generic Attributes:** Any custom attribute (e.g., `:multiple="false"`, `:active="false"`) falls through to the default branch and writes directly to the DOM as `multiple="false"` or `active="false"`.

When integrating Web Components built with Lit, Stencil, or native Custom Elements:

```html

```

Under standard HTML and DOM semantics, `element.hasAttribute('multiple')` returns true. Lit's boolean converter therefore treats the element as `multiple` regardless of the `"false"` string.

Adding `:?` allows developers to explicitly declare any arbitrary or standard attribute as a boolean toggle. This cleanly avoids having `hx-live` maintain or perpetually update a rigid, hardcoded registry of standard HTML5, ARIA, and custom boolean attributes.

---

#### Proposed Behavior & Truthiness Evaluation
When hx-live processes attributes matching the pattern `^(?:hx-live:|\:)\?([a-zA-Z0-9_-]+)$:`

1. Extract Attribute Name: Strip the `:?` or hx-live:? prefix (e.g.,` :?selected -> selected, :?checked -> checked`).

2. Evaluate Truthiness: Coerce the expression result to determine attribute presence.

3. Toggle Attribute: Invoke native `element.toggleAttribute(attrName, isTruthy)`.

Evaluation Rules:

- true, non-empty strings (e.g., `"active"`) -> Add/retain attribute (``)

- `false`, literal string `"false"` -> Remove attribute (``)

- `""` (empty/blank string) -> Remove attribute (prevents empty interpolation from activating flags)

- `null, undefined, 0, NaN `-> Remove attribute

```javascript
const boolMatch = name.match(/^(?:hx-live:|\:)\?([a-zA-Z0-9_-]+)$/);

if (boolMatch) {
const targetAttr = boolMatch[1];
const val = evaluate(expr, el);

const isFalsy =
val === false ||
val === null ||
val === undefined ||
val === 0 ||
Number.isNaN(val) ||
(typeof val === 'string' && (val.trim() === '' || val.trim() === 'false'));

el.toggleAttribute(targetAttr, !isFalsy);
}
```
---

#### Why This Fits `hx-live`
- Zero Breaking Changes: Existing `:attr `expressions remain untouched.

- Web Component First-Class Support: Solves a major interoperability blocker when using modern Web Components with `hx-live`.

- Standard Idiom: Follows the established `?` boolean convention popularized by Lit and the broader Web Components ecosystem.

---

#### Willingness to Contribute
I would be happy to submit a Pull Request.

Contributor guide

Open the contributing guide

Research direction

The payload names no source file or test. Start by tracing hx-live's attribute-binding evaluation and existing native-boolean handling; then verify both :? and hx-live:? forms, including the listed truthy and falsy values, while confirming existing :attr expressions remain unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
frontend
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.