Search code examples
javascriptvue.jsnuxt.jscodemirrorui-codemirror

Using CodeMirror with Vuejs/Nuxtjs results in error 'CodeMirror' is not defined when I the server reloads


I am implementing the CodeMirror to one of the textarea in my Nuxtjs/Vuejs application. I would like to beautify the textarea as per the XML.

Sometimes the CodeMirror works perfectly but sometimes when I reload the page I get the error:

Test.vue
33:18  error  'CodeMirror' is not defined  no-under

So initially it works perfectly but when I try to make some changes to any file in the project and when the Nuxtjs/Vuejs server reloads again to incorporate the new changes then I get the error error 'CodeMirror' is not defined

I am not understanding why do I get the error sometimes and I do not get it some other time. As I have added the required CDN and done the steps mentioned in various answers and articles, I would expect that it does not throw the error at all. Can someone please help me with this issue?

Steps followed:

  1. Added the CDN to my nuxt-config.js: Scripts:
    script: [
      {
        src:"text/javascript",
        src:"https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.32.0/codemirror.min.js"
      },
      {
        src:"text/javascript",
        src:"https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.32.0/mode/xml/xml.min.js"
      }
    ],

CSS:

{
 rel: "stylesheet",
 href:"https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.63.1/codemirror.min.css"
}

Following is my Test.vue:

<template>
  <div>
    <div class="row">
      <div class="col-md-5">
        <div class="row">
          <div class="col-md-12">
            <textarea
              id="test"
              v-model="xmlInput"
              class="form-control"
              placeholder="XML Document"
              spellcheck="false"
              data-gramm="false"
              @input="convertToJSON()"
            />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      xmlInput: ''
    }
  },
  methods: {
    convertToJSON () {
      console.log('ONE')
      const cm = CodeMirror.fromTextArea(document.getElementById('test'), {
        mode: 'application/xml',
        lineNumbers: true,
        matchBrackets: true,
        styleActiveLine: true,
        lineWrapping: true,
        tabSize: 2,
        value: 'console.log("Hello, World");'
      })
      cm.setSize(500, 500)
    }
  }
}
</script>

<style scoped>
textarea {
  height: 78vh;
  white-space: nowrap;
  resize: both;
}

::-webkit-input-placeholder {
  color: #f1948a;
  text-align: center;
}
</style>

Can someone please help me out with this issue? What am I doing wrong here? Any suggestions would be really appreciated. Thanks in advance.

Sandbox for re-creating issue: https://codesandbox.io/s/boring-water-g14zd?file=/pages/index.vue

Error in Sandbox: enter image description here


Solution

  • You can do the following things to make it work.

    • First, you don't have to re-initialize the codemirror editor on each input change @input="convertToJSON()"
    • You may initialize the editor when the component mounts.

    Code

    <template>
      <div>
        <div class="row">
          XML Dat
          <div class="col-md-5">
            <div class="row">
              <div class="col-md-12">
                <textarea
                  id="test"
                  v-model="xmlInput"
                  class="form-control"
                  placeholder="XML Document"
                  spellcheck="false"
                  data-gramm="false"
                />
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>
    
    export default {
      data() {
        return {
          xmlInput: "",
        };
      },
      mounted() {
        // https://stackoverflow.com/questions/53981928/using-codemirror-cannot-set-property-modeoption-of-undefined
        const editor = document.getElementById("test");
        editor.value = "";
        /** eslint-next-line */
        const cm = CodeMirror.fromTextArea(editor, {
          mode: "application/xml",
          lineNumbers: true,
          matchBrackets: true,
          styleActiveLine: true,
          lineWrapping: true,
          tabSize: 2,
          value: 'console.log("Hello, World");',
        });
    
        cm.setSize(500, 500);
      },
    };
    

    Here is the working codesandbox link - https://codesandbox.io/s/falling-cdn-5o0t6?file=/pages/index.vue

    If you want to use codemirror npm module, here is the link for the working codesandbox for that - https://codesandbox.io/s/boring-water-g14zd?file=/pages/index.vue