1
votes

I have an app which calls a web service in the created() function and populates a property of the root data object. The property is passed via a prop to a child component and using the Chrome dev tools I can see that the prop data is available on the child component.

The problem I have is that I try to set data properties in the child component using values passed via the prop I end up with undefined property data. If I use the Chrome inspection tools and add a breakpoint I can see that the prop is an observable object in the form of {__ob__: Observer} and as such, I cannot directly access any of the data. My suspicion is that the child object sets it's data properties before the web service call has completed in the root.

How can I overcome this?

I've created a JsFiddle for this: https://jsfiddle.net/ProNotion/a8c6nqsg/

Vue.component("mycomponent", {
    template: '#my-component-template',
    props: ["customer_data"],
    data() {
        return {
            form_data: {
                customerEmail: this.customer_data.customerEmail1
            }
        }
    }
});

new Vue({
    el: "#app",
    data() {
        return {
            customer: {}
        };
    },
    methods: {
        init() {
            var self = this;
            axios.get("https://0bb1313e-b089-432e-b6bc-250f6162d7f0.mock.pstmn.io/GetCustomerData")
            .then(response => {
                self.customer = response.data;
            }).catch(response => {
                console.error(response);
            });
        }
    },
    created() {
        this.init();
    }
});

Here is my HTML markup:

<div id="app">
    <mycomponent :customer_data="customer" />
</div>

<script type="x-template" id="my-component-template">
    <div>
        <p>{{form_data.customerEmail1}}</p>
    </div>
</script>
1
Try <p>{{ customer_data.customerEmail1 }}</p>. The issue is that customerEmail: this.customer_data.customerEmail1 only runs once and is not assigning a reference so when customer_data is updated, your customerEmail property is notPhil
My example is simplified unfortunately, I need to set the initial values of form_data based on the data from the parent but they could later be changed as the values will be bound to form fields. What you are suggesting is fine for presentational data but unfortunately won't resolve my issue for editable data. What you have described, if I understand correctly, is what I suspected so how can I delay the assignment of the data until the parent property is populated by the API call?ProNotion
@Phil I guess I could configure a watch for customer_data and set the data values for form_data however if the parent data should for some reason change it would overwrite any changes to the child component data?ProNotion

1 Answers

1
votes

Check response data type and format

console.log(typeof response.data) // string
{ "customerEmail1": "[email protected]", } // Remove `,`

You must parse to JSON type

axios.get(...).then(response => {
  self.customer = JSON.parse(response.data.replace(',', ''))
})


deep

Deep watching will be detect nested value changes inside Objects

Vue.component("mycomponent", {
  template: '#my-component-template',
  props: ["customer_data"],
  data() {
    return {
      form_data: {}
    }
  },
  watch: {
    customer_data: {
      handler (val) {
        this.form_data = val;
      },
      deep: true
    }
  }
});

Demo: https://jsfiddle.net/ghlee/f4gewvqn