Cannot read property 'value' of undefined

Keywords: node.js Javascript SQL Vue xml

Error in v-on handler: "TypeError: Cannot read property 'value' of undefined"

Errors are reported as follows:

The above error occurred while running the Vue project because its container was initialized before it was generated.

First, check whether there are the following operations

//The original operation of fetching dom
document.getElementById('textarea');
//After correction, the operation of taking demo in Vue
this.$refs.textarea

If the problem hasn't been solved, it is that $refs still can't get the value, that is, it can't get the sub component object in the El dialog dialog box, and all returned objects are undefined. Add the following on the outside,

this.$nextTick(function () {

});

For example, I can't get the value of this.$refs.textarea in my this. Initialize() method. It's undefined all the time. I'll add it outside

this.$nextTick(function () {
    this._initialize();
});

If the problem hasn't been solved, you need to open El dialog first to initialize the pop-up box. Only when El dialog is initialized can you get the sub components in Vue's rendering engine.

As follows, what I want to do is to open a pop-up box. The pop-up box is a table of the form form. There is an element in the table that is used to edit the code online. It supports the highlighting of each code language. The core code is as follows

<template>
  <div>
    <!-- Operation button --> 
    <el-button @click="handleAdd">Newly added</el-button>

    <!-- Dialog content -->  
    <el-dialog :title="title" :visible.sync="open" width="1000px">
      <el-form ref="form" :model="form" label-width="80px">
        <el-form-item label="Script content">
          <div class="in-coder-panel">
            <textarea ref="textarea"></textarea>
            <el-select class="code-mode-select" v-model="mode" @change="changeMode">
              <el-option v-for="mode in modes" :key="mode.value" :label="mode.label" :value="mode.value">
              </el-option>
            </el-select>
          </div>
        </el-form-item>
      </el-form>
    </el-dialog>

  </div>
</template>

<script>
  // Introduce global instance
  import CodeMirror from 'codemirror'
  // Core style
  import 'codemirror/lib/codemirror.css'
  // After the theme is introduced, you need to specify the theme in options to take effect
  import 'codemirror/theme/idea.css'

  // You need to introduce a specific syntax highlighting library to have the corresponding syntax highlighting effect
  // codemirror officially supports dynamic loading of corresponding syntax highlight library through / addon/mode/loadmode.js and / mode/meta.js
  // However, vue does not seem to be able to dynamically load the corresponding JS after instance initialization, so the corresponding JS is introduced in advance here
  import 'codemirror/mode/javascript/javascript.js'
  import 'codemirror/mode/css/css.js'
  import 'codemirror/mode/xml/xml.js'
  import 'codemirror/mode/shell/shell.js'
  import 'codemirror/mode/sql/sql.js'

  //Code completion prompt
  import 'codemirror/addon/hint/anyword-hint.js';
  import 'codemirror/addon/hint/css-hint.js';
  import 'codemirror/addon/hint/html-hint.js';
  import 'codemirror/addon/hint/javascript-hint.js';
  import 'codemirror/addon/hint/show-hint.css';
  import 'codemirror/addon/hint/show-hint.js';
  import 'codemirror/addon/hint/sql-hint.js';
  import 'codemirror/addon/hint/xml-hint.js';

  export default {
    name: "Code",

    props: {
      // External incoming content for two-way binding
      value: String,
      // Syntax type passed in from outside
      language: {
        type: String,
        default: null
      }
    },

    data() {
      return {
        // What's real inside
        code: '#!/bin/bash\n' +
        'cd /root/\n' +
        'list=(`ls`)\n' +
        ' \n' +
        'for i in ${list[@]}\n' +
        'do\n' +
        '   if [ -d $i ]\n' +
        '   then\n' +
        '       cp -r $i /tmp/\n' +
        '   fi\n' +
        'done',
        // Default syntax type
        mode: 'shell',
        // Editor instance
        coder: null,
        // Default configuration
        options: {
          // Indentation format
          tabSize: 4,
          // Subject, corresponding subject library JS needs to be introduced in advance
          theme: 'idea',
          // set number
          lineNumbers: true,
          line: true,
          extraKeys: {"Ctrl": "autocomplete"},
        },
        // The syntax highlighting type that supports switching. The corresponding JS has been introduced in advance
        // MIME type is used, but text / as prefix is written dead when specified later
        modes: [{
          value: 'css',
          label: 'CSS'
        }, {
          value: 'javascript',
          label: 'Javascript'
        }, {
          value: 'html',
          label: 'XML/HTML'
        },  {
          value: 'x-sh',
          label: 'Shell'
        }, {
          value: 'x-sql',
          label: 'SQL'
        }],
        // Pop up layer title
        title: "",
        // Show pop-up layer or not
        open: false,
    },

    methods: {
      // Initialization
      _initialize() {
        // Initialize the editor instance, pass in the text field object and default configuration to be instantiated
        this.coder = CodeMirror.fromTextArea(this.$refs.textarea, this.options)
        // Editor assignment
        this.coder.setValue(this.value || this.code)

        // Supports two-way binding
        this.coder.on('change', (coder) => {
          this.code = coder.getValue()

          if (this.$emit) {
            this.$emit('input', this.code)
          }
        })

        // Attempt to get syntax type from parent container
        if (this.language) {
          // Get specific syntax type object
          let modeObj = this._getLanguage(this.language)

          // Determine whether the syntax passed in by the parent container is supported
          if (modeObj) {
            this.mode = modeObj.label
          }
        }
      },
      // Get the current syntax type
      _getLanguage(language) {
        // Find the incoming syntax type in the list of supported syntax types
        return this.modes.find((mode) => {
          // All values ignore case for comparison
          let currentLanguage = language.toLowerCase()
          let currentLabel = mode.label.toLowerCase()
          let currentValue = mode.value.toLowerCase()

          // Because the real value may not be standardized, for example, the real value of Java is x-java, so it is said that value and label are compared with the incoming syntax at the same time
          return currentLabel === currentLanguage || currentValue === currentLanguage
        })
      },
      // Change mode
      changeMode(val) {
        // Modify the syntax configuration of the editor
        this.coder.setOption('mode', `text/${val}`)

        // Get the modified syntax
        let label = this._getLanguage(val).label.toLowerCase()

        // Allows the parent container to listen for the current syntax value through the following functions
        this.$emit('language-change', label)
      },

      /** Button operation */
      handleAdd() {
        this.open = true;
        this.title = "New script";
        this.$nextTick(function () {
          this._initialize();
        });
      },
    }
  };
</script>

<style lang="stylus" rel="stylesheet/stylus">
  .in-coder-panel
    flex-grow 1
    display flex
    position relative

    .CodeMirror
      flex-grow 1
      z-index 1
      .CodeMirror-code
        line-height 19px

    .code-mode-select
      position absolute
      z-index 2
      right 10px
      top 10px
      max-width 130px
</style>

The final rendering is as follows

Posted by almystersv on Tue, 14 Apr 2020 07:11:20 -0700