Stimulus excels at adding sprinkles of interactivity to your web apps. Let’s say you want to make an element on your page editable, like a todo entry, or a title for your blog page. We can use a Stimulus controller that will listen for a double click event, insert an input
tag that looks just like the element we double clicked, and the handle the enter
key being pressed to stop editing, and move those changes back to the element we double clicked.
Getting Started
I’m assuming you’ve setup your page to properly pull in Stimulus Controllers. The Handbook has instructions if you’re new and need to get started.
Let’s add the Stimulus controller, action, and target annotations to our header tag.
<h1 data-controller="inplace-editor"
data-action="dblclick->inplace-editor#doubleClick"
data-target="inplace-editor.editable">Here is a header</h1>
This h1
tag listens for the dblclick event, and is set as the editableTarget
in our Stimulus Controller.
Now, create a Stimulus controller named inplace_editor_controller.js
.
Here is the first part of the controller. We import Stimulus, and create a subclass of Controller:
import { Controller } from "stimulus"
export default class extends Controller {
Then we set our editableTarget
:
static targets = ["editable"]
Here we handle the double click event. We’ll create an input
tag called editor, and set it’s value to the value of our target. We’ll set editor’s style to match the target, so that it looks seamless.
doubleClick(event) {
event.preventDefault()
let editor = document.createElement("input")
editor.value = event.target.innerText
let style = window.getComputedStyle(event.target)
editor.style.cssText = style.cssText
We’ll listen for the enter
and escape
keys, and stop editing when those are typed.
editor.addEventListener('keypress', function(event) {
var key = event.which || event.keyCode;
if (key === 13 // 13 is enter
|| key == 27) { // 27 is escape
this.editableTarget.innerText = editor.value
this.editableTarget.classList.remove("editable--hidden")
editor.remove()
}
}.bind(this));
We’ll attempt to position the cursor close to where the double click event occurred, and then insert the editor element below our target.
let selection = window.getSelection()
editor.setSelectionRange(selection.anchorOffset, selection.anchorOffset)
this.editableTarget.insertAdjacentElement('afterend', editor)
this.editableTarget.classList.add("editable--hidden")
}
}
In order for the input to appear just like the target, we’ll apply a css class that will hide the target when we’re editing, and show it again when editing is complete. Here is what I’m using, and it can go anywhere you have your CSS:
.editable--hidden {
display: none;
opacity: 0;
}
In Closing
Now we have some slick interactivity on our web page. Depending on where this fits into your app, you’ll want to also save the changes, but I think that depends on what your editing. Here’s a tutorial that you could work from to remotely save the changes, also using stimulus.
Feel free to leave comments or questions below.
Want To Learn More?
Try out some more of my Stimulus.js Tutorials.
2 comments on “Let’s Make an Editable Header using Stimulus.js”
Hi there! Your site is great! I’ve learned a lot and it seems to be the most decent resource regarding stimulusjs. Thank you!
I implemented a similar functionality as you’ve got here, but instead of inserting an input element I just set contenteditable=true.
(https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content)
so helpfull thank you