tachi
tachi

Reputation: 37

Vuejs2 issue passing data changes between children

Another issue with a project I am working on.

I have the following vuejs2 parent-child structure

Within the product template I initiate the sibling components

The colourSelect component takes a comma delimited string and turns it into a drop down list. Whenever the selected option changes it emits the colour back to the product component which has a data variable "colour"

This appears to work fine.

The product-image component takes the product colour as a prop.

Whenever the colour changes I want the product-image component to detect it and trigger it to go get the relevant image. But its not detecting the change in colour.

Vue.component('product', {
props: ['productID', 'images', 'product'],
data: function () {
    return {
        colour: 'Navy',
    }
},
computed: {
    returnColour: function (colour) {
        // this.colour = colour
        //return colour
    }
},
template: '<transition name="list"><li class="moving-item" id="productID">' + 
'<product-image :productID="productID" :images="getImage(product.productID)" :colour="colour"></product-image>' +
'<colourSelect :colours="product.colour" :productID="product.productID" v-on:set-colour="setColour(colour)"></colourSelect>' +
'</li></transition>',
methods: {
getImage: function (listItemId) {
        var images = this.images.filter(function (item) {
            return returnCleanedData(item.Products_x003a_ID) === listItemId
        })

    },
    setColour: function (colour) {
        console.log('in main colour emit')

        this.colour = colour
        console.log(this.colour)
    }

}
});

Vue.component('colourSelect', {
props: ['productID', 'colours', 'set-colour'],
template: '<select  v-bind:id="getID()" class="form-control input-xs" :disabled=" isActive" v-bind:class="{disabledSelect: isActive}" v-on:click="setColour(productID)">' +
'<colourOption v-for="colourItem in colourArray">{{ colourItem.colour }}</colourOption>' +
'</select>',
data: function() {
    return {
        isActive: false
    }
},
computed: {
    colourArray: function () {
        //splits data and applies it to the select

    }

},
methods: {
    getID: function () {
        return 'colourSelect' + this.productID;
    },
    **setColour: function (productID) {**
        //yeah used jquery here
        var colour = $('#colourSelect' + productID).val()
        this.$emit('set-colour', colour)
    }
}
});

Vue.component('product-image', {
props: ['productID', 'images', 'colour'],
template: '<p><slot></slot><img :src="getImage(productID, images, colourSelected)" class="productImagePosition img-responsive img-rounded"></img></p>',
data: function () {
    return {
        isActive: false,
        selectedColour: this.colour
    }
},
computed: {
    colourSelected: function () {
        console.log('colour change detected')
        return this.colour
    }

},
methods: {
    getID: function (test) {
        return 'colourSelect' + this.productID;
    },
    getImage: function (listItemId, images, colour) {

        console.log('selected colour')
        console.log(colour)

        //filter images to the specific colour and return link
    },
}
});

The issue appears to be related to this line in the product template

v-on:set-colour="setColour(colour)"

When the child component emits the set-colour data back, the product is correctly running this method. But the product-image doesn't detect the change to its prop.

If i change the line to v-on:set-colour="setColour()" it will actually detect the change in the product-image but will error due to no data being passed.

Within the product-image component I have tried referencing a computed value (colourSelected) instead of the prop within the template which has no effect.

Any ideas?

Thanks

Upvotes: 1

Views: 152

Answers (1)

kimuraz
kimuraz

Reputation: 31

On product-image add a watcher to the colour prop:

watch: {
    colour(value) {
        // make changes here
    },
},

Upvotes: 1

Related Questions