Component communication in Vue.js unable to render properly - javascript

In the Parent component I have:
<todo-item v-for="(todo, index) in todos" :key="todo.id" :todo="todo" :index="index">
</todo-item>
which just iterates through todos array and gets each todo object and by using props passes each Object and its index to the child component. todo-item registered in Child component.
todos is an array of objects:
todos: [
{
'id': 1,
'title': 'Object 1'
},
{
'id': 2,
'title': 'Object 2'
}
]
Child component:
<template>
<div class="todo-item">
<div class="todo-item-left">
<div>{{ todo.title }}</div>
</div>
</div>
</template>>
<script>
export default {
name: 'todo-item',
props: {
todo: {
type: Object,
required: true
},
index: {
type: Number,
required: true
}
}
}
</script>
I don't know why it doesn't render each todo on the page, I have a blank page. Even though in Vue DevTools It shows that I have these objects.
Did I miss something?
EDIT:
There is an error, sorry the error flag were off hence didn't saw it.
Error message:
[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
As you can see above I did register the component in Child component.
And yes I did import the child component in Parent component by doing:
//Parent component
import ToDoItem from './ToDoItem'
export default {
name: 'todo-list',
components: {
ToDoItem,
},

You have problem with cases so you should import that component in parent one as follows :
import TodoItem from './TodoItem'
and register it like :
export default{
....
components:{
TodoItem
}
....
}
for more details check this

a common mistake
dont forget import child component in parent component
import ChildComponent fromt './ChildComponent';
export default{
components:{
ChildComponent
}
}

Related

Vue Prop Sync on multiple levels (TypeScript & JavaScript & ClassStyle)

I just started programming with Vue and ts/js so please forgive me if I miss something obvious :)
I am trying to pass a prop down two levels. If level 3 modifies the prop it also changes on level 2 but not on level 1.
Level 1 is a component I wrote and it is written in ts.
<template>
<Child :varr.sync="obj.attr" />
</template>
export default Parent class extends Vue {
obj: Object = {
attr: [1, 2, 3]
};
}
Level 2 is a component I wrote and it is written in ts.
<template>
<ChildsChild :layout.sync="arr" />
</template>
export default Child class extends Vue {
#PropSync("varr", { type: Array }) arr!: number[];
}
Level 3 is a component I DID NOT write and it is written in js.
export default {
props: {
layout: {
type: Array,
required: true,
}
}
}
When you pass something down to a child, you need to be careful to not update the prop directly on the child, because this is actually re-rendered every time the parent updates.
In your case, I'm not really sure why the PropSync isn't working. The similar pattern I've seen before is separating out the prop and adding a watcher as below
i.e.
Parent
<template>
<Child :varr.sync="obj.attr" />
</template>
export default Parent class extends Vue {
obj: Object = {
attr: [1, 2, 3]
};
}
Child:
<template>
<ChildsChild :layout.sync="passed_varr" />
</template>
export default Child class extends Vue {
props {
varr: {
type: Object
}
}
data: instance => ({
passed_varr: instance.varr,
}
watch: {
passed_varr: {
handler() {
this.$emit('update:varr', this.passed_varr);
},
deep: true,
},
},
}
In this case, the prop varr is synced with the parent component, so when layout is updated in the grandchild, it syncs with child.passed_varr which has a watcher to emit an update to parent.varr
Looking at the docs here it seems like PropSync is doing a similar thing, so not sure on the particular differences

TypeError: Cannot read property '_wrapper' of undefined

I am trying to update the props data sent to a component on a button click to a single component in vue.
Button click triggers an action loads the data from a config. But this throws the error and the error message was not clear. Find the error here https://imgur.com/a/0psUWKr
If I pass the data directly without the button actions, it works fine.
My Main component
<template>
<div>
<MyList v-if="listItems" :elements="listItems"/>
<button #click="showSlider">Show Slider</button>
</div>
</template>
<script>
// imports the components and config files
export default {
name: "ListView",
data() {
return {
listItems: []
};
},
components: {
MyList
},
methods: {
showSlider: function() {
this.listItems.push(configs['elements'])
},
</script>
NOTE: If i provide the data to listItems by default it works
And MyList file
<template>
<ul>
<li v-for="each in elements" :key="each.id">
{{each.name}}
</li>
</ul>
<template>
<script>
// imports the components and config files
export default {
name: "MyList",
props: {
elements: {
type: Array
}
}
</script>
It should work, in general. But in my case, the issue is with push in the following function.
showSlider: function() {
this.listItems.push(configs['elements'])
},
Storing the same from Vuex and using dispatcher to update the same works like a charm. And I use computed property to load the state from the vueX and pass it to MyList

Passing data from parent to child via props in v-for in VueJS 2

I went through similar questions but I couldn't find the answer and none of them worked for me.
Vuejs v-for Passing data Parent to Child
Vue - Passing parent data with same key name in v-for to child component
vue js how to pass data from parent, v-for loop list to child component with method
Pass data object from parent to child component
Vue.js - Pass in Multiple Props to Child in V-For
VUE / VUEX: How To Pass Data From Parent Template To Child Template
Parent.vue
<div class="col-sm-2" v-for="(item,index) in itemsData" :key="index">
<ItemWidget :item="item" />
</div>
<script>
import { mapState, mapActions } from "vuex";
import ItemWidget from "#/components/item/ItemWidget";
export default {
components: { ItemWidget },
computed: {
...mapState("item", ["itemsData"])
},
created() {
this.getItemList();
},
methods: {
...mapActions("item", ["getItemListX"]),
getItemList() {
this.getItemListX();
}
}
};
</script>
ItemWidget.vue
<template>
<div class="label">
<div class="label-value">{{ item.code }}</div>
</div>
</template>
<script>
export default {
props: ["item"]
};
</script>
itemsData is taken from the vuex by using MapState to the parent and itemsData is populated using created() method in the parent via an axios call in the vuex.
Error 1.
[Vue warn]: Error in render: "TypeError: _vm.item is undefined"
Error 2.
TypeError: "_vm.item is undefined"
How can I fix this?
Update
itemsData: [
{
code: "Test",
}
]
You should populate itemsData in computed method using ...mapState
Parent.vue
export default {
data: function () {
return {
items: this.itemsData
}
},
computed:{
...mapState('module/namespace', ['itemsData'])
}
}
<div class="col-sm-2" v-for="(item,index) in items" :key="index">
<ItemWidget :item="item" />
</div>
There is another way to declare your props:
<template>
<div class="label">
<div class="label-value">{{ item.code }}</div>
</div>
</template>
<script>
export default {
props: {
type: Object,
default: null
}
};
</script>

Vue js - pass data within two components in the same level

I have data that I need to pass from one component1 to another component2.
I don't use vuex or router.
Components tree:
-Parent
--Component1
--Component2
From first component1 I make ajax request, retrieving info and pushing to data.
board: [1,2,3,4,5]
And I need access that retrieved data in component2
Can I do It without vuex or router ?
Thank you :)
You could emit an event to parent from component1 having as parameters the updated board and in the parent one receive that and pass it through props to component2
In component1 :
this.$emit("sendToComp2",this.board);
in the parent component :
<template>
<component1 #sendToComp2="sendTo2"/>
...
<component2 :boards="boards" />
....
</template>
data:{
boards:[]
},
methods:{
sendTo2(boards){
this.boards=boards
}
}
component2 should have property called boards
props:["boards"]
The idea is that you have a Parent component which has at least two child components. The child components can trigger an event in the parent component and from Parent to child. So, if Component1 needs to send a message to Component2, it can trigger an event to Parent and then Parent trigger an event for Component2. Example:
<script>
export default {
name: 'Car',
methods: {
handleClick: function() {
this.$emit('clickedSomething')
}
}
}
</script>
and
<template>
<div>
<Car v-on:clickedSomething="handleClickInParent" />
<!-- or -->
<Car #clickedSomething="handleClickInParent" />
</div>
</template>
<script>
export default {
name: 'App',
methods: {
handleClickInParent: function() {
//...
}
}
}
</script>
Source: https://flaviocopes.com/vue-components-communication/
You have to follow the "common ancestor pattern".
Consider the following Parent component:
<template>
<div>
<child-one :onData="onDataFromChildOne"></child-one>
<child-two :newData="dataToChildTwo"></child-two>
</div>
</template>
<script>
export default {
name: "Parent",
data() {
return {
dataToChildTwo: null
}
},
methods: {
onDataFromChildOne(data) {
this.dataToChildTwo = data;
}
}
}
</script>
The ChildOne component will receive a function as a prop named onData that should be called when the ajax call is finished. Then:
<script>
import axios from 'axios';
export default {
name: "ChildOne",
props: ['onData'],
beforeMount() {
axios
.get('/data')
.then(res => {
this.onData(res.data);
});
}
}
</script>
When onData gets executed, dataToChildTwo will be updated and ChildTwo will receive the new data.

Vue.js - Dynamic component import in data and computed properties

I have component 'Page' that should display a component which is retrieved via its props.
I managed to get my component loads when I harcode my component path in my component data like this :
<template>
<div>
<div v-if="includeHeader">
<header>
<fv-header/>
</header>
</div>
<component :is="this.componentDisplayed" />
<div v-if="includeFooter">
<footer>
<fv-complete-footer/>
</footer>
</div>
</div>
</template>
<script>
import Header from '#/components/Header/Header';
import CompleteFooter from '#/components/CompleteFooter/CompleteFooter';
export default {
name: 'Page',
props: {
componentPath: String,
includeHeader: Boolean,
includeFooter: Boolean
},
data() {
componentDisplayed: function () {
const path = '#/components/my_component';
return import(path);
},
},
components: {
'fv-header': Header,
'fv-complete-footer': CompleteFooter,
},
}
</script>
But with the data I cannot refer to my props within my function as this is undefined.
I tried to used computed properties instead of data but I have the error "src lazy?0309:5 Uncaught (in promise) Error: Cannot find module '#/components/my_component'. But the module exists! But maybe not at that time ?
computed: {
componentDisplayed: function () {
const path = `#/components/${this.componentPath}`;
return import(path);
},
},
There must be away to deal with that but I am quite a beginner to vue.js :)
Instead of trying to import the component in your child component, instead import it in the parent component and pass the entire component as a prop.
<template>
<div :is="component" />
</template>
<script>
export default {
name: "page",
props: {
component: {
required: true
}
}
};
</script>
And in the parent
<page :component="component" />
and
import Page from './components/Page';
// and further down
data () {
return {
component: HelloWorld
}
}

Categories