Skip to content

Instantly share code, notes, and snippets.

@pauloevpr
Created January 7, 2024 19:47
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pauloevpr/c0bae76e7e9e6e824953489184e899ce to your computer and use it in GitHub Desktop.
Save pauloevpr/c0bae76e7e9e6e824953489184e899ce to your computer and use it in GitHub Desktop.
Simple HTMX extension to allow cloning <template> elements in the DOM to avoid a round trip to the server.
htmx.config.useTemplateFragments = true
htmx.defineExtension('clone', {
onEvent: function (name, evt) {
if (name === 'htmx:beforeRequest') {
if (evt.detail.elt) {
const get = evt.detail.elt.getAttribute('hx-get')
if (get && get.startsWith('clone:')) {
const selector = get.substring(6)
//console.log('htmx-clone: Intercepting xhr request to inject template with selector:', selector)
const template = document.querySelector(selector)
let templateContent = ''
if (!template) {
console.error(
'htmx-clone: No element found for selector: ' +
selector
)
} else {
if (template.tagName !== 'TEMPLATE') {
console.error(
'htmx-clone: Found element is not a <template>',
template
)
} else {
const templateNode =
template.content.cloneNode(true)
const tempDiv = document.createElement('div')
tempDiv.appendChild(templateNode)
templateContent = tempDiv.innerHTML
}
}
const xhr = evt.detail.xhr
Object.defineProperty(xhr, 'readyState', { writable: true })
Object.defineProperty(xhr, 'status', { writable: true })
Object.defineProperty(xhr, 'statusText', { writable: true })
Object.defineProperty(xhr, 'response', { writable: true })
Object.defineProperty(xhr, 'responseText', {
writable: true,
})
;(xhr.readyState = 4),
(xhr.status = 200),
(xhr.statusText = 'OK'),
(xhr.response = templateContent),
(xhr.responseText = templateContent),
(xhr.send = () => {
xhr.onload()
})
xhr.clonedNode
}
}
}
},
})
<template id="new-todo">
<input
name="title"
hx-post="/create-todo"
hx-swap="outerHTML"
/>
</template>
<ul>
<li>Todo 1</li>
<li>Todo 2</li>
<li>Todo 3</li>
</ul>
<button
hx-get="clone:#new-todo"
hx-target="ul"
hx-swap="beforeend"
>
Add Todo
</button>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment