Cannot copy props to data in child component in Vue - javascript

I have a child component SecondPage.vue. Props are passed to this component from parent component. Props are passed to child on click event. Then I'm trying to copy these props to data in SecondPage.vue. But when I use vue devtools, I can see, that data in child component is clear.
According to devtools, after click props in child are provided, but data (genQ, isA) is empty.
Where is the mistake?
SecondPage.vue
export default {
name: "SecondPage",
props: ["generalQuestInfo", "isActive", "getIconClass"],
data: function(){
return {
genQ: Object.assign({}, this.generalQuestInfo), //empty in devtools
isA: this.isActive //empty in devtools
}
}
}

Vuex store solved my problem!!!

Related

Using props in BeforeMount or Mounted- VUE.JS

I have prop in child component -> kpi_kalite[]
Parent component-> mounted():
*(This kpi_kalite is created in parent component's data)
axios.get(URL+ "/KPI/").then(response=>{
console.log(JSON.parse(JSON.stringify(response.data)))
this.kpi_kalite.push(response.data[0])
})
I do 'get request' in parent componenet and i push the response.data to kpi_kalite[] (parent component)
And i use this array for props.
Then, I want to do console.log(this.kpi_kalite) in beforeMount or Mounted.
But this props in not using.
methods : {
set_input(){
console.log(this.kpi_kalite)
for(const i in this.kpi_kalite){
console.log(i)
console.log(JSON.parse(JSON.stringify(this.kpi_kalite))) // output
// "undefined"
}
}
},
beforeMount() {
this.set_input()
}
console output : undefined
Could you help me? ,Before HTML-css loaded, I need parent component's data in child component
There is a post by LinusBorg about the order of lifecycle hooks for parent and child:
There’s nothing weird or wrong about it, it all follows from the
lifecylce logically.
beforeCreate() and created() of the parent run first.
Then the parent’s template is being rendered, which means the child components get created
so now the children’s beforeCreate() and created() hooks execute respecitvely.
these child components mount to DOM elements, which calls their beforeMount() and mounted() hooks
and only then, after the parent’s template has finished, can the parent be mounted to the DOM, so finally the parent’s beforeMount()
and mounted() hooks are called.
END
Also, there is a nice diagram here.
Child components are mounted before the parent component is mounted. Therefore, console.log(this.kpi_kalite) in the child component does not print the data gotten from the axios in the parent. So, if you do not render the child component at first, it will not be mounted because it is not created. If you render the child component after the axios is completed, it will be created and mounted. Then, console.log will print the value of kpi_kalite gotten from the axios in the parent.
ParentComponent:
<ChildComponent v-if="renderChildComponent" :kpi_kalite="kpi_kalite" />
data() {
return {
kpi_kalite: [],
renderChildComponent: false,
};
},
mounted() {
axios.get(URL+ "/KPI/").then(response=>{
console.log(JSON.parse(JSON.stringify(response.data)))
this.kpi_kalite.push(response.data[0])
this.renderChildComponent = true;
})
},

Avoid mutating a prop directly: Instead, use a data or computed property based on the prop's value. Prop being mutated: "items"

I am passing the param for breadcrumbs in array format for each page.
I get the following warning
Avoid mutating a prop directly since the value will be overwritten
whenever the parent component re-renders. Instead, use a data or
computed property based on the prop's value. Prop being mutated:
"items"
Breadcrumbs Component
<template>
<vs-row class="vs-breadcrumb-row" vs-type="flex" vs-justify="space-around">
<vs-col
type="flex"
vs-justify="center"
vs-align="center"
vs-lg="12"
vs-sm="12"
vs-xs="12"
code-toggler
>
<vs-card class="br-0">
<h4 class="card-title mb-0 d-flex">
<vs-row vs-justify="space-between" vs-align="center">
{{ pageTitle }}
<div class="d-flex align-items-center">
<vs-breadcrumb separator="chevron_right"
:items="breadcrumbLinks"
></vs-breadcrumb>
</div>
</vs-row>
</h4>
</vs-card>
</vs-col>
</vs-row>
</template>
<script>
export default {
name: "Breadcrumbs",
props: {
pageTitle: {
type: String
},
breadcrumbLinks: {
type: Array
}
}
};
</script>
I am getting the following error.
The layout structure is.
Dashboard - sending the array param to default layout and default layout pass it to breadcrumb
Default Layout
Breaducrumb
Dashboard Component
export default {
name: "Dashboard",
components: {
DefaultLayout
},
data: () => ({
breadcrumbLinks: [
{
title: global.vm.$t('breadcrumbs.home'),
url: ""
},
{
title: global.vm.$t('breadcrumbs.dashboard'),
active: true
}
],
})
};
The props sent to children should not be modified outside it's parent component.
Dashboard - sending the array param to default layout and default layout pass it to breadcrumb
Default Layout
Breaducrumb
Your breadcrumbLinks prop is been changed outside of Dashboard component where it was created, so, you are probably making changes on this prop on Default Layout or Breaducrumb components.
If you avoid mutating props outside its components you'll avoid this warnings.
But it's a warning, not an error, what it says is that if the parent component gets mutated, the child components, in this case Default Layout and Breaducrumb will be updated with the values previously or initially set on the parent component.
So any change you do to a prop on any child component will be lost, this may not be a problem and make your code work perfectly but it is certainly a pattern that should be avoid.
If you want to mutate props:
Send a $emit to the parent that has this props as data and performe the changes there.
Here you can read about custom events - VueDocs
Use a global state manager as Vuex
In your case you may not need any of this, please, show us the function that modifies breadcrumbLinks prop.
It should be somewhere in DefaultLayout or on Breadcrumb components, but for sure it is not on the code you posted.

Accessing called component data in main template

Hopefully this is an easy fix and i can just chalk it up to my inexperience with Vue
In my main template, I can use v-for to access any objects in the templates data return and I'm successfully loading a separate component in my html
However, when I try to access info from that external component outside of my component call it doesn't show.
I'm trying to create something that I can turn into a modal which would be separate from all imported components but still be able to access data from any component in my main template's modal
How can I access data from any called component in my main template?
<template>
<!--this content shows-->
<subItem-component></subItemComponent>
<!--this doesn't-->
<p v-for="subItem in subItems>{{ subItem.title }}</p>
</template>
subitemComponent
data() {
return {
subItems: [],
}
}
You cannot access the scope of a child component within the parent. Usually, you would load the required data in the parent, if you are needing it there, and then pass it along to the child component as a prop like this:
ParentComponent:
<template>
<sub-item-component sub-item="subItem"></sub-item-component>
<p v-for="subItem in subItems>{{ subItem.title }}</p>
</template>
<script>
import SubItemComponent from '...';
export default {
name: 'ParentComponent',
components: {
SubItemComponent
},
data () {
return {
subItems: []
};
}
}
</script>
SubItemComponent:
<template>
{{ subItem }}
</template>
<script>
export default {
name: 'SubItemComponent',
props: {
subItem: {
type: Array,
required: true
}
}
}
</script>
You could also use a Vuex store to persist the data in one place. With this approach you would have access to the data from each component and do not have pass the data from component to component. To use a store like Vuex, you need to define a Vuex state and at least one mutation method to add the data.
If you want to communicate from the child up to the parent, the way to go would be by using events. You would use a listener on the child component in the parent component like this:
<sub-item-component #new-sub-item="handleNewSubItem"></sub-item-component>
You need to define a method handleNewSubItem in the parent, which is reacting each time the new-sub-item event is thrown in the child component.
The event can then be thrown within the script part of the child component like this:
const subItem = { test: 123 };
this.$emit('new-sub-item', subItem);
You don't. Your options are:
The parent component needs to manage the data and pass it down to its children via props. Child components can then subsequently emit events which the parent can listen for and modify its state.
Use a state handler outside of both the components like Vuex or Apollo (if using GraphQL).

Why is this Vue prop not reacting to change?

I have a Prop in my component that is a User object, I then have this function:
onChange: function(event){
this.$v.$touch();
if (!this.$v.$invalid) {
this.$axios.put('update',{
code:this.user.code,
col:event.target.name,
val:event.target.value
}).then(response => {
this.user[event.target.name]=event.target.value
});
}
}
I can see in the Vue console debugger that the correct attribute has been updated, this attribute exists when the component is created but the template where I reference it does not refresh:
<p>Hi {{user.nickname}}, you can edit your details here:</p>
This is all within the same component so I'm not navigating to child or parent. I'm sure props have been reactive elsewhere in my code?
Ok, it seems this is intended behaviour. According to the documentation
https://v2.vuejs.org/v2/guide/components-props.html in the scenario that I have it should be handled as:
The prop is used to pass in an initial value; the child component wants to use it as a local data property afterwards. In this case,
it’s best to define a local data property that uses the prop as its
initial value:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
Usually components should be reactive to Props, though i have had experiences where it was non-reactive so i added the prop to a watcher and put the functional call there.
props: ["myProp"],
watch:{
myProp(){
// ... your functions here
}
}

Vuex store can be manipulated when passing state to component

Not quite sure if this is a post for stackoverflow but i really struggle with this one.
I'm using vuex and vue1. I love vuex because you can't/shouldn't change the store without mutations.
But now I'm passing a state object to a (child) component. When I'm changing the value in the child component. Vuex allows me to change it.
Is there a specific reason why this can be done or is this just bad practice?
Parent component
<child-component :pass-value="stateValueParent"> </child-component>
vuex: {
getters: {
stateValueParent: (state) => state.values.stateValueParent
}
}
Child component
export default {
props: [
'passValue'
],
let value = this.passValue
// This is changed but it should right?
value = 'newValue'

Categories