1
votes

In Vuetify, you can set up code like below and the VForm component can automatically check if all inputs within VForm are valid without passing any props back and forth. How can I achieve this functionality for my own form and input components in Vue 2?

<template>
  <v-form v-model="formIsValid">
    <v-text-field :rules="[required]"></v-text-field>
  </v-form>
</template>

<script>
  data() {
    return {
      formIsValid: false
    }
  },
  methods: {
    required(val) {
      return !!val || 'Required.'
    }
  }
</script>
1

1 Answers

4
votes

You can explore vuetify source code to learn how they do that.
First, you have to understand provide/inject, https://vuejs.org/v2/api/#provide-inject
A very simplified version of their concept is like below,

VForm.vue

export default {
  data() {
    return {
      inputs: []
    }
  },
  provide () {
    // provide this Form component for child, so child can register itself
    return { form: this }
  },
  methods: {
    register(input) {
      this.inputs.push(input);
    },
    validate() {
      // loop through child registered inputs,
      // run every child.validate() to validate all child
      this.inputs.forEach(input => {
        input.validate();
      });
    }
  }
}

VInput.vue

export default {
  props: {
    rules: {
      default: () => [],
      type: Array
    }
  },
  // inject parent VForm component
  inject: ['form'],
  created() {
    // with inject above, you can use this.form to reference parent VForm
    this.form.register(this);
  },
  methods: {
    validate() {
      // use rules to validate input
    }
  }
}

Usage
anything provide by v-form can be used in v-input with inject.

<template>
  <v-form>
    <v-input :rules="rules"/>
  <v-form/>
</template>

Most of the logic is in these files, and vuetify did much more than the logic above. Learn to study open source code, open source project is awesome.

  1. VForm: https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/components/VForm/VForm.ts
  2. registrable mixin used by VForm: https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/mixins/registrable/index.ts
  3. VInput: https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/components/VInput/VInput.ts
  4. validatable mixin used by VInput: https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/mixins/validatable/index.ts