Skip to content →

Build a Markdown Editor in Stimulus.js like in Vue.js

I’ve been looking into different Javascript frontends to see if they made my development life easier. I’ve been looking specifically to see if they improve on some Stimulus sprinkles and server rendered HTML. One interesting example was converting a text area from markdown to html. It uses marked to perform the conversion, and it uses lodash to set up a timer for the conversion. I’ll show you today how you perform the same behavior using a stimulus controller, without the need for the lodash dependency.



Vue.js has a very compact format for HTML annotations, so the HTML is pretty compact, and it includes the required javascript libraries:

<script src=""></script>
<script src=""></script>

<div id="editor">
  <textarea :value="input" @input="update"></textarea>
  <div v-html="compiledMarkdown"></div>


Stimulus has the advantage of not using ids to connect HTML to the Javascript code. Although it does require more characters, I think you’ll see the clarity of what this HTML snippet attempts to setup:

<div class="editor" data-controller="markdown-editor">
  <textarea data-action="input->markdown-editor#convertToMarkdown"></textarea>
  <div data-target="markdown-editor.viewer"></div>

You see that there is a controller in charge of this div, you see where the action comes from, and you see where the compiled markdown is going to go.



Vue.js uses a standard component, keyed off of the div’s id property. It set’s up some default data, handles changes to the textarea, and updates the compiled markdown html:

new Vue({
  el: '#editor',
  data: {
    input: '# hello'
  computed: {
    compiledMarkdown: function () {
      return marked(this.input, { sanitize: true })
  methods: {
    update: _.debounce(function (e) {
      this.input =
    }, 300)


We’ll use a Stimulus controller to watch for updates to the text editor, compile the markdown, and update the markdown view. This goes in a markdown_editor_controller.js:

import { Controller } from "stimulus"
import marked from 'marked/lib/marked.js'

export default class extends Controller {

  static targets = ["viewer"]

  convertToMarkdown(event) {
    this.viewerTarget.innerHTML = marked(, {sanitized: true});;

marked.js is added via webpacker, so you need to run

yarn add marked

This will make marked importable in our controller.


I hope this shows some of the similarities and differences between Vue.js and Stimulus.js. Hopefully you have another data point when deciding on what type of Javascript framework to pick. And if you’re using Ruby and Rails, you can leverage it’s server rendered HTML to do a lot of the layout work for you, without needing to resort entirely to a JSON API and Javascript templating.

You can see that both frameworks let you write interactive web apps. Vue.js requires more setup in Javascript, and Stimulus.js puts more in the HTML structure.

Comments or Questions? Find me on twitter @jpbeatty

Want To Learn More?

Try out some more of my Stimulus.js Tutorials.

Curious about picking the right Javascript front end?

Enter your email below, and you won’t miss the next Stimulus JS Tutorial, that will teach you how to accelerate your front end development.

Published in ruby on rails Stimulus JS Tutorial

Comments are closed.