htmx-json
v1.9.6
Published
Support for json response in htmx
Downloads
211
Readme
htmx-json
Support for json response in htmx.
What is this?
This htmx extension adds support for using json response in htmx. By using a combination of attributes and templates it can easily update the dom with new values from the json response. This way you can write your html in the html file and rely on a small json response.
Install
Just reference it from a cdn like unpkg, just like you do with htmx.
<script src="https://unpkg.com/htmx-json"></script>Usage
Given an api endpoint that returns this json:
{
"title": "Data",
"show": true,
"list": ["very", "simple", "and", "cool"]
}Add attributes and templates to an html
<body hx-ext="json-swap">
<div hx-get="/api/data" hx-trigger="load, every 60s" hx-swap="json">
<h2 json-text="title">This will be replaced by the value of `title`</h2>
<p json-show="show">This will only be shown when `show` is true</p>
<ul>
<template json-each="list">
<li>${$this}</li>
</template>
</ul>
</div>
</body>You can use these attributes:
json-textjson-ifjson-each@attribute.propertyjson-show/json-hidejson-with
They are described below
Features
json-text
Add the json-text attribute to change the textContent of the element.
<span json-text="name">This will contain the value of the `name` property</span>
<span json-text="`My name is ${name}!`"
>Use JavaScript template tags to interpolate text</span
>
<span json-text="isSomething ? 'Yes' : 'No'"
>You can add any JavaScript expression to the attribute</span
>You can also use json templating directly in the text content. The following are equivalent to the above three.
<span>${name}</span>
<span>My name is ${name}!</span>
<span>${isSomething ? 'Yes' : 'No'}</span>The disadvantage of doing it like this is that the template string is shown while the page loads and is only swapped out when the json is applied. This makes this more suitable for use inside templates, which aren't shown until the json is applied
You can use json-ignore to stop interpolation of text, when it would cause conflicts:
<span json-ignore>$123</span>json-ignore
Ignore entire subtree from being processed. json-ignore also ignores any attribute after it, so you can stop processing in the middle of the attributes:
<span json-ignore @data-test="this will be ignored"></span>json-if
You can conditionally have html using a template tag with json-if, and optionally json-else-if and json-else
<template json-if="someCondition">
<span>This is only shown if `someCondition` is truthy.</span>
</template>
<template json-else>
<span>This is only show if the condition is falsy</span>
</template>You can have any number of json-else-if to create a kind of switch statement:
<template json-if="status == 'OK'">
<span>Everything is OK</span>
</template>
<template json-else-if="status == 'ERROR'">
<span>There is an error</span>
</template>
<template json-else-if="status == 'WARN'">
<span>There is a warning</span>
</template>
<template json-else>
<span>Status is unknown</span>
</template>json-each
Loop over a list using json-each, for example give the following json:
{
"list": [
{ "id": "first", "value": "First"}
{ "id": "second", "value": "Second"}
{ "id": "third", "value": "Third"}
{ "id": "fourth", "value": "Fourth"}
]
}<ul>
<template json-each="list">
<li>${value}</li>
</template>
</ul>You should use json-key to refer to a unique string value in each item if you want the list to update correctly:
<ul>
<template json-each="list" json-key="id">
<li>${value}</li>
</template>
</ul>You can also supply an object, where the entries will be iterated over. Note that json-key is ignored, and you will experience weird things if the keys are integer values.
@attributes
Set any attribute using @attribute="value":
<a @href="`mailto:${email}`">${name}</a>.property
Set any property using .property="value":
<span .style.background-color="color">${name}</span>The property name needs to be converted from camelCase to kebab-case for it to be valid html.
This means you can do very dirty stuff:
<div .inner-h-t-m-l="html">
This will be replaced with the contents of `html` using innerHTML!
</div>json-show and json-hide
Show or hide (using display: none) an element.
<div json-show="condition">This will only be visible if condition is true</div>
<div json-hide="condition">This will only be visible if condition is false</div>
<div json-show="condition" style="display: none">
This will be hidden until condition becomes true
</div>If you want it to be initially hidden you can use style="display: none" to hide it until json is applied.
<input>
Form fields are special, they will automatically get their value from the json using the name attribute. For example:
{
"text": "something",
"checked": true,
"choice": "second"
}<input name="text" />
<small
>This will have the value `something` since `name="text"` and `"text":
"something"`</small
>
<input name="checked" type="checkbox" />
<small>This will be checked since `name="checked"` and `"checked": true`</small>
<input name="choice" value="first" type="radio" /> First
<input name="choice" value="second" type="radio" /> Second
<input name="choice" value="third" type="radio" /> Third
<small
>The second option will be selected because `name="choice"`, `value="second"`
and `"choice": "second"`</small
>If you need to set the value to something other than the value directly you can use .value="something" to do so:
<input name="hour" .value="new Date(dateTime).getHour()" />json-with
Go into an object using json-with to select the property to use:
<div json-with="address">
<strong>Street: ${street}</strong>
<span>Postal code: ${postCode}</span>
<span>Country: ${country}</span>
</div>Properties
$this: The current object$parent: The parent object, insidejson-withorjson-each$index: The current index, insidejson-each$key: The current key, insidejson-each
If you have nested json-with and/or json-each you can use $parent multiple times, and to get the $index and $key further up, for example $parent.$index.
