1
votes

I created a component for displaying some information in a nice looking way. This component is just a wrapper for the content, which is rendered inside the parent component. The parent component implements the child component this way:

    <my-component v-for="item in items" :key="item.id">
        <template slot="header">
            {{ item.title }}
        </template>
        <template slot="meta">
            <div>
                <template v-if="typeof item.additionalData != 'undefined'">
                    {{ item.additionalData.text }}
                </template>
            </div>
        </template>
    </my-component>

Its working fine, until I want to change the data. items is a variable in the parent component and at render time, the data is parsed in the right way. When I change something inside of items after rendering, the child component doesn't recognize it. The reason is because the item.additionalData is added through an AJAX call after the component was already rendered.

The docs say

Everything in the parent template is compiled in parent scope; everything in the child template is compiled in child scope.

but it seems like this is only true at render time.

Am I not able to use my component this way or is there a solution for that?

2
Here they explain how to wait for the Ajax call to complete, and then render: laracasts.com/discuss/channels/vue/…Randy
By the way, welcome to StackOverflow. If any of the answers below solved your problem, please be sure to mark the one that worked best for you as accepted so the community can benefit from your feedback. If your question is still unsolved, please update your answer with further information so we can help you get to the bottom of the issue.Jason Smith

2 Answers

1
votes

From the docs:

Due to the limitations of modern JavaScript (and the abandonment of Object.observe), Vue cannot detect property addition or deletion. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the data object in order for Vue to convert it and make it reactive.

So I suspect the fact that your item.additionalData field is initially undefined means that it's getting missed by Vue later on when it's added. The best solution is to make item.additionalData defined, but set to null or false. If that's not possible, consider using Vue.set(object, key, value) as outlined here.

0
votes

I had a similar problem with adding a search icon to the item template. The way I resolved it was to make (in terms of your example) additionalData a computed property which is then fully reactive. This is the basic form:

computed: {
  additionalDataText() {
    return item.additionalData ? item.additionalData.text : null
  }
} 

I'm unclear if your code shows the parent component or the child component.
As it is, the simplest change you can make requires the computed property to receive item as a parameter like so:

computed: {
  additionalDataText() {
    return function (item) {
      return item.additionalData ? item.additionalData.text : null
    }
  }
} 

and your template would be

<my-component v-for="item in items" :key="item.id">
    <template slot="header">
        {{ item.title }}
    </template>
    <template slot="meta">
        <div>
            <template v-if="additionalDataText(item)">
                {{ additionalDataText(item) }}
            </template>
        </div>
    </template>
</my-component>

This technique is from Unirgy's answer to this question: Can I pass parameters in computed properties in Vue.Js. There's a bit of controversy there about this method, but I tried it in my project and it seems to work.
Note, in the referenced question the accepted answer suggests using a method, but this does not give you the reactivity you require.