Skip to content

Instantly share code, notes, and snippets.

@frullah
Last active September 16, 2021 09:14
Show Gist options
  • Save frullah/9e0cd19c0f01779b361690bbb18259d8 to your computer and use it in GitHub Desktop.
Save frullah/9e0cd19c0f01779b361690bbb18259d8 to your computer and use it in GitHub Desktop.
Stimulus JS dynamic form
import { Controller } from 'stimulus'
// used for changing form fields dynamically based on what user want in one page
export default class extends Controller {
static values = { targetContainerId: String, templateId: String }
async connect() {
// store array of DocumentFragment by id
this.templates = {}
// store container elements by id
this.containers = {}
this.currentContainer = null
// container placeholder
this.container = null
if (this.templateIdValue) {
this.element.value = this.templateIdValue;
}
this.targetContainerIdValueChanged()
this.onChange({ target: this.element })
}
async onChange(e) {
// retrieve if there is an existing template
const templateId = e.target.value
let template = this.templates[templateId]
if (template === undefined) {
const templateElement = document.getElementById(templateId)
if (!templateElement || !('content' in templateElement)) {
return
}
template = templateElement.content
templateElement.remove()
// store template
this.templates[templateId] = template
}
/**
* replace container with template container if template exist
* it does not need to replace it for the first time appendChild
*/
const container = this.containers[templateId]
if (container) {
this.replaceCurrentContainer(container)
} else {
// clone new container
const newContainer = this.container.cloneNode(true)
newContainer.appendChild(template)
this.replaceCurrentContainer(newContainer)
// store containers
this.containers[templateId] = this.currentContainer
}
}
replaceCurrentContainer(newContainer) {
this.currentContainer.replaceWith(newContainer)
this.currentContainer = newContainer
}
targetContainerIdValueChanged() {
const container = document.getElementById(this.targetContainerIdValue)
this.currentContainer = container
this.container = container.cloneNode(true)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment