Skip to content

Blogging On Rails

Everything on Rails!

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.

HTML

Vue.js

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="https://unpkg.com/marked@0.3.6"></script>
<script src="https://unpkg.com/lodash@4.16.0"></script>

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

Stimulus.js

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>
</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.

Javascript

Vue.js

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 = e.target.value
    }, 300)
  }
})

Stimulus.js

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(event.target.value, {sanitized: true});;
  }
} 

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

yarn add marked

This will make marked importable in our controller.

Conclusion

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.

Feel free to leave a comment or question below.

Want To Learn More?

Try out some more of my Stimulus.js Tutorials.

Make Interactivity Default 

Make your web app interactive now with easy to implement and simple to add HOTWire integrations. 

Enter your email and get a free sample of my HOTWire Tutorials ebook.

We won’t send you spam. Unsubscribe at any time.

Leave a Reply

Your email address will not be published. Required fields are marked *