Custom Vue Material md-Input how to get isDirty or

2019-08-23 11:44发布

问题:

I would like to create my own CustomMdInput, with basic validation. I would like to implement a input that work that way:

I use a <fp-input v-model="test"></fp-input>, and It is important, that when this input is required, when someone clicked on it or typesomething (turns 'touched' or 'dirty' property), and next defocus this input and go to the another input, the previous one stays Invalid with all the validation, so i have something like this:

<template>
  <div class="md-layout-item">
    <md-field>
      <label :for="id">Imię</label>
      <md-input :name="id" :id="id" :required="required" v-model="value" :ref="id" @input="emitValue()"></md-input>
      <span class="md-error">Imię jest obowiązkowe</span>
    </md-field>
  </div>
</template>

<script>
export default {
  name: 'FpInput',
  props: {
    value: {
      required: true
    },
    id: {
      required: true,
      type: String
    },
    required: {
      default: false,
      type: Boolean
    }
  },
  methods: {
    emitValue () {
      this.$emit('input', this.$refs[this.id].value)
    }
  }
}
</script>

<style scoped>

</style>

But i don't know how to check if this input isDirty or isTouched, and how can i set Validity of this input to check isFormValid after submit

回答1:

give you an example

const MyInput = {
			template: '#myInput',
			props: ['value'],
			data () {
				return {
					inputValue: this.value,
					dirty: false,
					touched: false,
					inValid: false
				}
			},
			methods: {
				validate () {
					if(this.inputValue.length<5){
						this.inValid = true
						this.dirty = true
					}else{
						this.inValid = false
						this.dirty = false
						this.touched = false
					}
				},
				emitValue() {
					this.validate()
					this.$emit('input', this.inputValue);
				}
			}
		}

		var app = new Vue({
		  el: '#app',
		  components: {MyInput},
		  data () {
		    return {
		    }
		  }
		})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	<div id="app">
	  <my-input value="5"></my-input>
	</div>

	<script type="text/x-template" id="myInput">
		<div>
      		<input v-model="inputValue" @input="emitValue()" @touchstart="touched = true" @mousedown="touched = true"/>
			<span v-show="(dirty || touched) && inValid">must be at least 5 letters</span>
			<div>dirty:{{dirty}}</div>
			<div>touched:{{touched}}</div>
			<div>inValid:{{inValid}}</div>
		</div>
	</script>

give you a full example

const MyInput = {
  template: '#myInput',
  props: ['value'],
  data () {
    return {
      inputValue: this.value,
      dirty: false,
      touched: false,
      inValid: false
    }
  },
  methods: {
    validate () {
      if(('' + this.inputValue).length<5){
        this.inValid = true
        this.dirty = true
      }else{
        this.inValid = false
        this.dirty = false
        this.touched = false
      }
    },
    emitValue(e) {
      this.validate()
      this.$emit('input', this.inputValue);
    }
  },
  created () {
    this.inputValue = this.value;
    this.validate();
    this.dirty = false;
  }
}

var app = new Vue({
  el: '#app',
  components: {MyInput},
  data () {
    return {
      inputList: new Array(4).fill('').map(o=>({val:5}))
    }
  },
  methods: {
    submit () {
      if(this.$refs.inputs.some(o=>o.inValid)){
        alert('you have some input invalid')
      }else{
        alert('submit data...')
      }
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	<div id="app">
  <form @submit.prevent="submit">
      <my-input ref="inputs" v-for="item in inputList" v-model="item.val"></my-input>
    <button type="submit">submit</button>
  </form>
</div>

<script type="text/x-template" id="myInput">
  <div>
        <input v-model="inputValue" @input="emitValue()" @touchstart="touched = true"/>
    <span v-show="(dirty || touched) && inValid">must be at least 5 letters</span>
  </div>
</script>