title: Best practice for implementing custom form in Vue
body: <p>My goal is to create a custom form component called <code>app-form</code> which provides <code>v-model</code> to access the validation. For the input I want to detect is also a custom component called <code>app-input</code>.<br />
  Here is my implementation so far.</p>
  <p><strong>app-form</strong></p>
  <pre class="lang-html prettyprint-override"><code>&lt;template&gt;
    &lt;div&gt;
      &lt;slot&gt;&lt;/slot&gt;
    &lt;/div&gt;
  &lt;/template&gt;
  </code></pre>
  <pre class="lang-js prettyprint-override"><code>const acceptedTags = ['app-input'];
  export default {
    /*
    props: value,
    data: isValid
    */
    updated() {
      // update isValid whenever the view changes
      this.checkValidation();
    },
    methods: {
      checkValidation() {
        this.isValid = true;
        this.checkValidation(this);
        this.$emit('input', this.isValid);
      },
      checkValidationRecursion(node) {
        if (acceptedTags.includes(node.$options.name)) {
            let result = node.checkValidation();
            this.isValid &amp;&amp;= result;
        }
        node.$children.forEach((child) =&gt; this.checkValidationRecursion(child));
      },
    }
  }
  </code></pre>
  <p><strong>app-input</strong></p>
  <pre class="lang-html prettyprint-override"><code>&lt;input
    :value=&quot;selfValue&quot;
    @input=&quot;onInput&quot;/&gt;
  </code></pre>
  <pre class="lang-js prettyprint-override"><code>export default {
    name: 'app-input',
    /*
    props: value,
    data: selfValue,
    */
    methods: {
      checkValidation() {
        let valid = true;
        /*
          this.rules = [(v) =&gt; !!v || 'Required'];
        */
        for (let f of this.rules) {
          let result = f(this.selfValue);
          if (typeof result === 'string') {
            valid = false;
          }
        }
        return valid;
      },
      // onInput() =&gt; update selfValue and emit
    },
    // watch: update selfValue
  }
  </code></pre>
  <p>In the code above, the <code>app-form</code> have to traverse the whole component tree to get the target inputs every time anything is updated. Is there any better way to achieve it?</p>