Databinding entire objects between child Vue components and the root Vue instance
General feedback

The use of the &lt;script&gt; tag as a template is nice and I have aimed to use that more frequently in my own projects when not using a larger template library. 

Doesn't it seem a bit redundant to have a component called applicant, which has a property called applicant? Perhaps a more generic name for those properties would be more appropriate - e.g. attributes. However, the advice below, which responds to your question, suggests binding the applicant to the model attribute instead of a property. 

Main question


  Since I'm passing the parent applicant object to the component and am modifying it directly through that passed in reference using the v-model directive am I not directly modifying the parent object so therefore keeping the data coupled as the docs recommended against.


Your question appears nearly identical to this SO question, though in your case you have working code and are passing an object instead of a single value. To follow the guidelines in the documentation, perhaps altering the code as described in the answer by asemahle would be an optimal route.


Change the property from applicant to value. 

props: ['value'],


And in the markup, use v-model instead of the property for applicant:

&lt;applicant v-model="form.borrower"&gt;&lt;/applicant&gt;
&lt;applicant v-model="form.coborrower"&gt;&lt;/applicant&gt;

Add applicant via the the local data properties:

data: function() {
    return {
        applicant: {}
    }
},

When the component is created, set the applicant to the value property:

created: function() {
    this.applicant = this.value;
}

Watch for changes on the local data property applicant and emit an event in response to that change

watch: {
    'applicant': function() {
        // When the internal value changes, we $emit an event. Because this event is 
        // named 'input', v-model will automatically update the parent value
        this.$emit('applicant', this.applicant);
    }
}



Below is a demonstration:



Vue.component('applicant', {
  template: '#applicant-container',
  props: ['value'],
  watch: {
    'applicant': function(valueChanged) {
      // When the internal value changes, we $emit an event. Because this event is 
      // named 'input', v-model will automatically update the parent value
      this.$emit('applicant', this.applicant);
    }
  },
  data: function() {
    return {
      applicant: {}
    }
  },
  created: function() {
    this.applicant = this.value;
  }
})

// Root Vue instance
const app = new Vue({
  el: '#app',
  data: {
    form: {
      borrower: {
        firstname: 'John',
        middlenames: '',
        surname: 'Rambo'
      },
      coborrower: {
        firstname: 'Homer',
        middlenames: '',
        surname: 'Simpson'
      }
    }
  }
});
.row {
  border: 2px solid #5CD7FF;
  margin: 2px;
  padding: 4px;
}
.label {
  font-style: italic;
}
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"&gt;&lt;/script&gt;

&lt;div id="app"&gt;
  &lt;h3&gt;Borrower:&lt;/h3&gt; in parent:{{ form.borrower }} 
  &lt;applicant v-model="form.borrower"&gt;&lt;/applicant&gt;
  &lt;h3&gt;Co-borrower:&lt;/h3&gt; in parent:{{ form.coborrower }}
  &lt;applicant v-model="form.coborrower"&gt;&lt;/applicant&gt;
&lt;/div&gt;
&lt;script type="x-template" id="applicant-container"&gt;
  &lt;div class="row"&gt;&lt;span class="label"&gt;Applicant Template:&lt;/span&gt;
    &lt;div class="form-group col-md-4"&gt;
      &lt;label&gt;Firstname&lt;/label&gt;
      &lt;input type="text" class="form-control" v-model="applicant.firstname" /&gt;
    &lt;/div&gt;
    &lt;div class="form-group col-md-4"&gt;
      &lt;label&gt;Middlename/s&lt;/label&gt;
      &lt;input type="text" class="form-control" v-model="applicant.middlenames" /&gt;
    &lt;/div&gt;
    &lt;div class="form-group col-md-4"&gt;
      &lt;label&gt;Surname&lt;/label&gt;
      &lt;input type="text" class="form-control" v-model="applicant.surname" /&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/script&gt;