Skip to content →

Let’s Make an Editable Header using Stimulus.js

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-editing" 
      data-target="inplace-editing.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) {
    let editor = document.createElement("input")
    editor.value =
    let style = window.getComputedStyle( = 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

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)

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.

Comments or Questions? Find me on twitter @jpbeatty

Want To Learn More?

Try out some more of my Stimulus.js Tutorials.

Get the next tutorial when it comes out!

Please enter your email below, and you won’t miss the next Stimulus JS Tutorial

Published in ruby on rails Stimulus JS Tutorial

Comments are closed.