I have a parent and a child. In the parent am passing 3 variables as props to the child. In the Child I am using the watch() to look for varaible changes. When the child is created for the 1st time the watch works as expected but when the data from the props in updated then DOM of the child is not updated. The watch function which is looking for data change of the variable is not running at all.
Here is my code. Its a bit lengthy so please bear with it.
Parentcomponent.vue
<template>
<div>
<button type="button" v-on:click="LoadCatalog()">Click me!! </button>
<div v-if="displayCategoryList" class="row">
<h3>Select Category Men</h3>
<select v-model="menCategory" v-on:change="passDataToChild()">
<option v-for="item in categoriesfordisplay.men" v-bind:key="item">
{{ item }}
</option>
</select>
<h3>Select Category Women</h3>
<select v-model="WomenCategory" v-on:change="passDataToChild()">
<option v-for="item in categoriesfordisplay.women" v-bind:key="item">
{{ item }}
</option>
</select>
</div>
<div v-if="displayData" class="row">
<div v-for="item in data_to_show_on_mainpage" v-bind:key="item" >
<button v-on:click="newfunction(item.cat,item.gender)" >
<img v-bind:src="item.data.image"> </img>
<p >{{ item.cat }}</p>
</button>
</div>
</div>
<category-items v-if="displayCategoryData" v-bind:gender="gender" v-bind:catsgory="catsgory" v-bind:catlog="catlog" ></category-items>
</div>
</template>
<script>
import axios from 'axios'
import CategoryItems from './CategoryItems'
export default {
name: 'GetCategoryItemsAndDisplayOne',
props: ['categoriesfordisplay','ismainpage', 'catalogselected'],
components:{
CategoryItems,
},
data(){
return {
IsMainPage_1 : "",
data_to_show_on_mainpage : [],
cat :[],
displayData : true,
menCategory : "",
WomenCategory : "",
displayCategoryList: true,
displayCategoryData : false,
CategoryFromImage : "",
//dataSentToChild : {}
gender : "",
catsgory : "",
catlog : ""
}
},
methods:{
passDataToChild(){
if(this.menCategory != ""){
this.catsgory = this.menCategory
this.gender = "men"
this.catlog = this.catalogselected
this.menCategory = ""
}else if(this.WomenCategory != ""){
this.catsgory = this.WomenCategory
this.gender = "women"
this.catlog = this.catalogselected
this.WomenCategory = ""
}
this.displayData = false
this.displayCategoryData = true
},
changevalue(){
this.data_to_show_on_mainpage = []
},
CatlogService(catlog_name,category,gender,mainpage){
let url = "http://localhost:5000/xyz/" + (this.catalogselected).replace(/'/g,"%27") +"/api/"+ (gender) + "/catalogvis/" + (category) +"/items"
axios.get(encodeURI(url)).then((resp)=>{
var jsonData = {"data": resp.data.response.Results.results[0] , "cat": category , "gender" : gender}
)
this.data_to_show_on_mainpage.push(jsonData)
})
.catch(err => {
console.log("we got an error the url is " + url)
console.log(err);
})
},
GetItemsToShowonMainPage(){
this.changevalue()
if(this.categoriesfordisplay.men_for_display.length>0){
for(let i =0;i<this.categoriesfordisplay.men_for_display.length;i++){
let category = this.categoriesfordisplay.men_for_display[i].replace(/"/g,"%27");
console.log(category)
this.CatlogService(this.catalogselected,category,'men',this.ismainpage)
}
}
if(this.categoriesfordisplay.women_for_display.length>0){
for(let i = 0;i<this.categoriesfordisplay.women_for_display.length;i++){
let category = this.categoriesfordisplay.women_for_display[i].replace(/"/g,"");
this.CatlogService(this.catalogselected,category,'women',this.ismainpage)
}
}
},
LoadCatalog(){
this.displayCategoryData = false
this.GetItemsToShowonMainPage()
this.displayData = true
this.displayCategoryList = true
},
newfunction(Cats,gender){
this.displayCategoryData = true
this.displayData = false
this.catsgory = Cats
this.gender = gender
this.catlog = this.catalogselected
}
},
created(){
this.GetItemsToShowonMainPage()
}
}
</script>
<style>
</style>
The Child component CategoryItems.vue is below
<template>
<div>
<h4>{{ genders }}</h4>
<h4>{{ category }}</h4>
<h4>{{ catalogue }}</h4>
</div>
</template>
<script>
export default{
name : 'CategoryItems',
props : ['gender','catsgory','catlog'],
data(){
return {
genders : "",
category : "",
catalogue : "",
}
},
watch : {
category : function(){
this.GetProducts()
}
},
methods:{
GetProducts(){
this.genders = this.gender
this.category = this.catsgory
this.catalogue = this.catlog
}
},
created(){
this.genders = this.gender
this.category = this.catsgory
this.catalogue = this.catlog
}
}
</script>
<style>
</style>
As You can see whenever the category variable in the child changes the function GetProducts should run but it is not happening. It is executed only when the child component is created.
Where I am going wrong with my logic. Thanks
As long as you're updating a reactive property (props, computed props, and anything in data ), Vue knows to watch for when it changes. All we have to do is update count , and Vue detects this change. It then re-renders our app with the new value!
If the key stays the same, it won't change the component, but if the key changes, Vue knows that it should get rid of the old component and re-create a new one. Every time that forceRerender is called, our prop componentKey will change.
To specify the type of prop you want to use in Vue, you will use an object instead of an array. You'll use the name of the property as the key of each property, and the type as the value. If the type of the data passed does not match the prop type, Vue sends an alert (in development mode) in the console with a warning.
To pass props dynamically to dynamic component in Vue. js, we can check the current component being rendered in component and pass in the props accordingly. to check the value of currentComponent in the currentProps` computed property. And we return an object with the props we want to pass into the child component .
You are only setting the child component's variable in the created
hook, therefor they are not reactive.
The best way is to make a reactive data based on the prop is to create a computed property based on that property :
computed: {
category: function() {
return this.catsgory;
},
},
This computed will be automatically updated whenever the props changes.
You also can watch the prop directly, and force the watcher to trigger immediately (take a look at the the API).
Your child component's watcher will look like this :
watch : {
category: {
handler: function() {
this.GetProducts();
},
immediate: true,
},
},
In my case, If initial props value(array) is undefind
, even if props change, render was not fired.
So I changed inital props value to empty array []
Then problem solved.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With