forum.vuejs.org - 20170102

Debugging component local state issues

by Matt

HTML

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.3/lodash.min.js"></script>

<div id="app">
  <json-input label="thing" v-model="obj.count"></json-input>
  <hr>Data: {{ obj }}
</div>

CSS

html,
div,
input {
  font-size: 14px;
  font-family: "Fira Mono";
  line-height: 24px;
  width: 90%;
}

input.dirty {
  border: 2px solid crimson;
}

JavaScript

Vue.component('json-input', {
  template: '\
  <div>\
  <input\
  	ref="input"\
   	v-bind:class="{ dirty: isDirty }"\
  	v-bind:value="format(value)"\
    v-on:input="parse($event.target.value)"\
    >\
  <hr>\
  isDirty: {{ isDirty }}\
  <br>\
  isObject: {{ isObject }}\
  <br>\
  isBoolean: {{ isBoolean }}\
  <br>\
  isNumber: {{ isNumber }}\
  <br>\
	isString: {{ isString }}\
  </div>\
  ',

  props: {
    // The form label/key
    label: {
      type: String,
      required: true
    },
    // The form value
    value: {
      required: true
    }
  },

  data() {
    return {
      // dirty is true if the type of the field doesn't match the original
      // value passed.
      dirty: false,
      // typeChecked is true when the type of the original value has been
      // checked. This allows us to validate user-input against the original
      // (expected) type.
      typeChecked: false,
      isObject: false,
      isBoolean: false,
      isNumber: false,
      isString: false
    }
  },
  computed: {
    isDirty: function() {
      return this.dirty
    }
  },
  methods: {
    // init determines the JS type of the field (once) during initialization.
    init: function() {
      this.typeChecked = false
      this.isObject = false
      this.isBoolean = false
      this.isNumber = false
      this.isString = false
      if (_.isPlainObject(this.value) || _.isArrayLikeObject(this.value)) {
        this.isObject = true
      } else if (_.isNumber(this.value)) {
        this.isNumber = true
      } else if (_.isBoolean(this.value)) {
        this.isBoolean = true
      } else if (_.isString(this.value)) {
        this.isString = true
      }
      this.typeChecked = true
    },
    // format returns a formatted value based on its type; Objects are
    // JSON.stringify'ed, and Boolean & Number values are noted to prevent
    // reading them back as strings.
    format: function() {
      // Check the types of our fields on the initial format.
      if...