vue-form
Version:
Form validation for Vue.js
248 lines (222 loc) • 7.42 kB
HTML
<html>
<head>
<title>vue-form example</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<style>
.required-field>label::after {
content: '*';
color: red;
margin-left: 0.25rem;
}
</style>
<script src="https://cdn.tinymce.com/4/tinymce.min.js"></script>
</head>
<body>
<div id="app" class="container py-5">
<p>Example showing vue-form usage with Bootstrap styles, validation messages are shown on field touch or form submission</p>
<vue-form :state="formstate" v-model="formstate" @submit.prevent="onSubmit">
<!--
<validate auto-label class="form-group required-field" :class="fieldClassName(formstate.name)">
<label>Comments</label>
<tinymce type="text" name="comments" class="form-control" required v-model="model.comments" v-input></tinymce>
<field-messages name="comments" show="$touched || $submitted" class="form-control-feedback">
<div>Success!</div>
<div slot="required">Comments is a required field</div>
</field-messages>
</validate>
-->
<validate auto-label class="form-group required-field" :class="fieldClassName(formstate.number)">
<label>Custom number</label>
<custom-number name="number" min="2" class="form-control" v-model="model.number"></custom-number>
<field-messages name="number" class="form-control-feedback">
<div>Success!</div>
<div slot="max">Number is too large</div>
<div slot="min">Number is too small</div>
<div slot="required">required</div>
</field-messages>
</validate>
<validate auto-label class="form-group required-field" :class="fieldClassName(formstate.name)">
<label>Name</label>
<input type="text" name="name" class="form-control" v-model="model.name" required />
<field-messages name="name" class="form-control-feedback">
<div>Success!</div>
<div slot="required">required</div>
</field-messages>
</validate>
<!--
<validate auto-label class="form-group required-field" :class="fieldClassName(formstate.name)">
<label>Custom number</label>
<input type="number" :min="min" max="11" name="number2" class="form-control" required v-model="model.number" />
<field-messages name="number2" class="form-control-feedback">
<div>Success!</div>
<div slot="required">Comments is a required field</div>
</field-messages>
</validate>
<validate auto-label class="form-group required-field" :class="fieldClassName(formstate.name)">
<label>Name</label>
<input type="text" name="name" class="form-control" required v-model.lazy="model.name">
<field-messages name="name" show="$touched || $submitted" class="form-control-feedback">
<div>Success!</div>
<div slot="required">Name is a required field</div>
</field-messages>
</validate> -->
<div class="py-2 text-center">
<button type="button" @click="changeStuff">changeStuff()</button>
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</vue-form>
<pre>{{formstate}}</pre>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script src="../dist/vue-form.js"></script>
<script>
console.log(Vue.version);
var options = {
inputClasses: {
valid: 'form-control-success',
invalid: 'form-control-danger'
}
}
var input = {
name: 'input',
bind: function(el) {
console.log('here');
}
};
var generatedIds = 0;
var tinymce = {
template: `
<div :class="{'pre-loader': isLoading}">
<div class="rich-textarea-toolbar"><div :id="elementId + '-toolbar'"></div></div>
<div :class="[className, {'invert-theme': invertTheme }]" class="input-richtext" :placeholder="placeholder" :id="elementId"></div>
</div>`,
data() {
generatedIds++;
return {
elementId: 'tinymce-inline-editor-' + generatedIds,
isLoading: true
};
},
props: {
value: String,
preset: {
type: String,
default: 'inline'
},
placeholder: String,
forceEmpty: Boolean,
disabled: Boolean,
forcedRootBlock: null,
invertTheme: Boolean
},
computed: {
className() {
if (this.preset === 'textarea') {
return 'input-textarea';
} else if (this.preset === 'inline' || this.preset === 'el') {
return 'inline-editor';
}
}
},
};
var customNumber = {
template: '<input type="number" :min="min" :max="max" v-model="input" />',
props: {
min: {
type: null,
default: 2
},
value: null
//type: String
},
data: () => ({ num: 5, input: null }),
watch: {
input (v) {
this.$emit('input', v)
}
},
computed: {
max () {
return this.num;
},
validationData () {
return {
type: 'number',
//min: this.min,
required: true,
max: this.max
}
}
},
created() {
this.input = this.value;
},
mounted() {
// this.$emit('vf:mounted', {
// type: 'number',
// min: this.min,
// max: this.max
// });
this.$emit('vf:watch', 'validationData');
setInterval(()=>{
this.num = this.num + 1;
//console.log(this.num)
}, 2000);
},
updated() {
// this.$emit('vf:updated', {
// type: 'number',
// min: this.min,
// max: this.max
// });
}
};
var vm = new Vue({
el: '#app',
mixins: [new VueForm(options)],
components: {
tinymce: tinymce,
customNumber: customNumber
},
directives: {
input: input
},
data: {
formstate: {},
model: {
name: '',
email: '',
phone: '',
department: null,
comments: '',
notValidated: '',
number: 7,
number2: 10
},
min: 6
},
methods: {
changeStuff () {
this.min = this.min + 1;
},
fieldClassName: function(field) {
if (!field) {
return '';
}
if ((field.$touched || field.$submitted) && field.$valid) {
return 'has-success';
}
if ((field.$touched || field.$submitted) && field.$invalid) {
return 'has-danger';
}
},
onSubmit: function() {
console.log(this.formstate.$valid);
}
}
});
</script>
</body>
</html>