UNPKG

vuetify

Version:

Vue Material Component Framework

145 lines (124 loc) 3.4 kB
// Components import VInput from '../VInput/VInput' // Mixins import mixins from '../../util/mixins' import BindsAttrs from '../../mixins/binds-attrs' import { provide as RegistrableProvide } from '../../mixins/registrable' // Helpers import { VNode } from 'vue' type ErrorBag = Record<number, boolean> type VInputInstance = InstanceType<typeof VInput> type Watchers = { _uid: number valid: () => void shouldValidate: () => void } /* @vue/component */ export default mixins( BindsAttrs, RegistrableProvide('form') /* @vue/component */ ).extend({ name: 'v-form', provide (): object { return { form: this } }, inheritAttrs: false, props: { disabled: Boolean, lazyValidation: Boolean, readonly: Boolean, value: Boolean, }, data: () => ({ inputs: [] as VInputInstance[], watchers: [] as Watchers[], errorBag: {} as ErrorBag, }), watch: { errorBag: { handler (val) { const errors = Object.values(val).includes(true) this.$emit('input', !errors) }, deep: true, immediate: true, }, }, methods: { watchInput (input: any): Watchers { const watcher = (input: any): (() => void) => { return input.$watch('hasError', (val: boolean) => { this.$set(this.errorBag, input._uid, val) }, { immediate: true }) } const watchers: Watchers = { _uid: input._uid, valid: () => {}, shouldValidate: () => {}, } if (this.lazyValidation) { // Only start watching inputs if we need to watchers.shouldValidate = input.$watch('shouldValidate', (val: boolean) => { if (!val) return // Only watch if we're not already doing it if (this.errorBag.hasOwnProperty(input._uid)) return watchers.valid = watcher(input) }) } else { watchers.valid = watcher(input) } return watchers }, /** @public */ validate (): boolean { return this.inputs.filter(input => !input.validate(true)).length === 0 }, /** @public */ reset (): void { this.inputs.forEach(input => input.reset()) this.resetErrorBag() }, resetErrorBag () { if (this.lazyValidation) { // Account for timeout in validatable setTimeout(() => { this.errorBag = {} }, 0) } }, /** @public */ resetValidation () { this.inputs.forEach(input => input.resetValidation()) this.resetErrorBag() }, register (input: VInputInstance) { this.inputs.push(input) this.watchers.push(this.watchInput(input)) }, unregister (input: VInputInstance) { const found = this.inputs.find(i => i._uid === input._uid) if (!found) return const unwatch = this.watchers.find(i => i._uid === found._uid) if (unwatch) { unwatch.valid() unwatch.shouldValidate() } this.watchers = this.watchers.filter(i => i._uid !== found._uid) this.inputs = this.inputs.filter(i => i._uid !== found._uid) this.$delete(this.errorBag, found._uid) }, }, render (h): VNode { return h('form', { staticClass: 'v-form', attrs: { novalidate: true, ...this.attrs$, }, on: { submit: (e: Event) => this.$emit('submit', e), }, }, this.$slots.default) }, })