field-input component for vee-validate
by gongzza
HTML
<script src="https://unpkg.com/[email protected]/dist/vee-validate.js"></script>
<script src="https://unpkg.com/[email protected]/dist/locale/ko.js"></script>
<div id="app">
<form class="ui form" @submit.prevent="onSubmit">
<field-input field="regist.email" type="text" rules="required|email" v-model="user.email"></field-input>
<field-input field="regist.name" type="text" rules="required" v-model="user.name"></field-input>
<field-input field="regist.password" type="password" rules="required|min:6" v-model="user.password"></field-input>
<field-input field="regist.password_confirmed" type="password" rules="required|confirmed:password" v-model="user.password_confirmed"></field-input>
<field-input field="regist.homepage" v-model="user.homepage" rules="url"></field-input>
<button type="submit" class="ui submit button">Submit</button>
</form>
</div>
<template id="field-input">
<div class="field" :class="{error: errors.has(fieldName, scope), required: isRequired}">
<label v-text="prettyName"></label>
<input :type="type" :name="fieldName" :value="value" @input="updateValue($event.target.value)">
<span class="error" v-if="errors.has(fieldName, scope)">
{{ errors.first(fieldName, scope) }}
</span>
</div>
</template>
CSS
@import url('https://unpkg.com/[email protected]/semantic.css');
span.error {
color: #9F3A38;
}
JavaScript
const attrs = {
email: '이메일',
name: '이름',
password: '패스워드',
password_confirmed: '패스워드 확인',
homepage: '홈페이지'
}
Vue.component('field-input', {
name: 'field-input',
template: '#field-input',
inject: ['$validator'],
props: {
value: {
required: true
},
field: {
type: String,
require: true
},
rules: [String, Object],
type: {
type: String,
default: 'text'
},
},
computed: {
prettyName() {
return attrs[this.fieldName]
},
fieldName() {
return this.field.includes('.')
? this.field.substring(this.field.indexOf('.') + 1)
: this.field
},
scope() {
return this.field.includes('.')
? this.field.substring(0, this.field.indexOf('.'))
: '__global__'
},
isRequired() {
if (!this.rules) {
return
}
return (typeof this.rules === 'string')
? this.rules.includes('required')
: this.rules['required']
}
},
methods: {
updateValue(val) {
this.rules && this.$validator.validate(this.fieldName, val, this.scope)
this.$emit('input', val)
},
getter() {
return this.value
},
context() {
return this
}
},
mounted() {
const options = {
scope: this.scope,
getter: this.getter,
context: this.context,
prettyName: this.prettyName
}
this.$validator.attach(this.fieldName, this.rules, options)
},
destroyed() {
this.$validator.detach(this.fieldName)
},
})
Vue.use(VeeValidate)
const dictionary = {
ko: {
messages: {
email: () => `올바른 이메일 형식이 아닙니다.`,
required: (field) => `필수 입력란입니다.`,
confirmed: (field, confirmedField) => `${confirmedField}와 일치하지 않습니다.`,
url: () => `올바른 URL 형식이 아닙니다.`
}
}
}
VeeValidate.Validator.updateDictionary(dictionary)
VeeValidate.Validator.setLocale('ko')
new Vue({
el: '#app',
data() {
return {
user: {
name: '',
email: '',
...