I try to use a prop in a computed value and i keep getting the error:
[Vue warn]: Error in render: "TypeError: Cannot read property 'length' of undefined"
found in
---> at src/cmps/space-details/space-imgs.vue
at src/pages/space-details.vue
at src/App.vue
Maybe i'm using the prop wrong?
the component:
<template>
<div v-if="imgUrls.length" class="space-imgs" :class="pics">
<img :src="img" v-for="(img, idx) in imgUrls.slice(0, 5)" :key="idx" />
</div>
</template>
<script>
export default {
props: { imgUrls: Array },
computed: {
pics() {
return `pics-${this.imgUrls.length}`;
},
},
};
</script>
and this is how i pass the prop:
<space-imgs :imgUrls="space.imgUrls" />
Thanks
Pass the prop like below. This will work.
<space-imgs :img-urls="space.imgUrls" />
For avoiding wrong prop data in component. initialize prop with default value.
props: {
imgUrls: {
type: Array,
default: [],
required: true
}
}
Your template will be first rendered before the prop is passed, making imgUrls undefined. So just do this: v-if="imgUrls".
Related
User.vue
<template>
<div>
<!-- <div class="cont-color">{{ user.name }} {{ user.age }}</div> -->
<div v-for="(item, key) in user" :key="key">
{{ item }}
</div>
</div>
</template>
<script>
import { datalisttwo } from "./datalisttwo";
export default {
name: "User",
data() {
return {
lists: datalisttwo,
};
},
computed: {
user: function () {
return this.lists.find((item) => item.cmd_id === this.$route.params.id);
},
},
};
</script>
Working code:- https://codesandbox.io/s/hardcore-cartwright-vi6qg?file=/src/components/User.vue
How to call specific value from an array in Vuejs.
At present, It is calling all values, from an array. But want to call only {{name}} and {{age}} values.
If i remove the v-for and write directly like this {{ user.name }} {{ user.age }} --> It is printing the array values, But getting error as
[Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'name')"
TypeError: Cannot read properties of undefined (reading 'name')
I think problem is in your computed block, use below solution
computed: {
user: function () {
return this.lists.find((item) => item.cmd_id === this.$route.params.id);
},
},
sandbox
In User.vue you have this comparison:
return this.lists.find((item) => item.id === this.$route.params.id);
but the data you use from datalisttwo.js does not have the property id but instead cmd_id
So that find result will always be undefined which is the error you see in the javascript console:
[Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'name')"
so you'll need to update your find to be the following:
return this.lists.find((item) => item.cmd_id === this.$route.params.id);
I guess you need to return an Array on that computed property. Use filter instead of find.
computed: {
user: function () {
return this.lists.filter((item) => {
if(item.cmd_id === this.$route.params.id) {
return item
}
})
}
}
I have two components
Parent: AjaxLoader.vue
<script>
export default {
name: 'AjaxLoader',
props: {
url: {},
},
render() {
return this.$scopedSlots.default({
result: `resultData of ${this.url}`,
});
},
};
</script>
Child: SearchInput.vue
<template>
<AjaxLoader url="/api/fetch/some/data">
<template slot-scope="{ result }">
<div>{{ result }}</div>
</template>
</AjaxLoader>
</template>
Now I can pass variable from parent to child and in child component can display parent result variable. In this case in result var should be resultData of /api/fetch/some/data.
My question is: How can I write this logic of child component into render function with JSX syntax ?
I tried:
<script type="text/jsx">
import AjaxLoader from './../ajax-loader/AjaxLoader.vue';
export default {
components: { AjaxLoader },
name: 'SearchInput',
render(h) {
return (
<AjaxLoader url="/api/fetch/some/data">
<template slot-scope="{ result }">
<div> {{ result }} </div>
</template>
</AjaxLoader>
);
},
};
</script>
But I got error: [Vue warn]: Error in render: "ReferenceError: result is not defined"
I already have installed plugins for JSX support of Vue.js
Thanks for help
I found solution for child component. Maybe it someone helps.
render(h) {
return (
<AjaxLoader url="/api/fetch/some/data">
{(props) => <div> {props.result} </div>}
</AjaxLoader>
);
},
My object looks like this :
{
"container_status": {
"name": "/dev-ms",
"port": {
"2233/tcp": [
{
"HostPort": "123"
}
]
}
}
}
I want to display value of key HostPort
I try like this :
console.log(data.container_status.port['2233/tcp'][0].HostPort)
It works
But There exist error :
[Vue warn]: Error in render: "TypeError: Cannot read property 'port' of undefined"
My vue component like this :
<template>
...
<v-flex xs4>
<p class="">{{data.container_status.port['6690/tcp'][0].HostPort}}</p>
</v-flex>
...
</template>
<script>
export default {
...
};
</script>
How can I solve this error?
I think that your data object is not ready in component loading, to solve this try this :
<p class="">{{!!data.container_status?data.container_status.port['6690/tcp'][0].HostPort:""}}</p>
or
<p class="" v-if="data.container_status">{{data.container_status.port['6690/tcp'][0].HostPort}}</p>
I would use a computed for something so complex, and the computed will update the value if data.container_status changes
computed: {
HostPort() {
if(!this.data.container_status) {
return '',
}
return this.data.container_status.port['6690/tcp'][0].HostPort
}
}
<p class="">{{HostPort}}</p>
to make sure that another property is not undefined I would use the get of lodash in the computed https://lodash.com/docs/4.17.15#get
I'm a begginer in web development and i'm trying to make a front end using vuejs and vuetify.
My problem is that i can't figure out why I can't pass an array of objects to a component.
My code is the following :
In my main page i got these lines to use the component :
<template>
...
<v-content>
...
<list-2 :objectsProps="clients"/>
...
</v-content>
...
</template>
-----------------------
<script>
import List2 from "./components/List2";
export default {
name: "App",
components: {
List2
},
data() {
return {
...
clients: [],
...
};
},
...
mounted() {
this.clients = [
{
title: "Client1",
description: "Unknown"
},
{
title: "Client2",
description: "Unknown"
},
{
title: "Pradier",
description: "Unknown"
}
];
}
};
</script>
And my component is like that:
<template>
<v-card>
<v-list two-line subheader>
<v-subheader>List</v-subheader>
<v-list-tile v-for="object in objects" :key="object.title" avatar>
<v-list-tile-avatar>
<v-icon x-large>account_circle</v-icon>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title>{{ object.title }}</v-list-tile-title>
<v-list-tile-sub-title>{{ object.description }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
</v-list-tile-action>
</v-list-tile>
</v-list>
</v-card>
</template>
<script>
export default {
name: "List2",
props: {
objectsProps: []
},
data() {
return {
};
},
computed:{
objects: function(){
return this.objectsProps
}
}
};
</script>
At this point, i don't have enough knowledge on vue to understand what is exactly going on here, but what i'm trying to do is to give a list of objects (which can be a list of clients or a list of vehicles or anything) to my component.
The List2 component shouldn't be aware of what it is displaying as long as it gets some objects with a title and a description.
I use a computed property on the component, because i don't know if it's recommended to do a v-for on the props.
And I constantly get this error :
TypeError: Cannot read property 'filter' of undefined
at render (vuetify.js:7048)
at createFunctionalComponent (vue.runtime.esm.js:4056)
at createComponent (vue.runtime.esm.js:4246)
at _createElement (vue.runtime.esm.js:4416)
at createElement (vue.runtime.esm.js:4353)
at vm._c (vue.runtime.esm.js:4485)
at List2.vue?36c9:37
at Proxy.renderList (vue.runtime.esm.js:3701)
at Proxy.render (List2.vue?36c9:13)
at VueComponent.Vue._render (vue.runtime.esm.js:4540)
Along with these warnings :
[Vue warn]: Invalid prop: type check failed for prop "objectsProps". Expected , got Array.
found in
---> <List2> at src/components/List2.vue
<VContent>
<VApp>
<App> at src/App.vue
<Root>
vue.runtime.esm.js:587 [Vue warn]: Error in render: "TypeError: Cannot read property 'filter' of undefined"
found in
---> <List2> at src/components/List2.vue
<VContent>
<VApp>
<App> at src/App.vue
<Root>
But i have no filter property in my main page or my component, so i don't get why...
So my question are : Is my approach correct, or am i doing it the wrong way?
What should I do to in order to make it work ?
And if you have some tips/advices for a beginner, i'm definetly up to get them !
Thank you !
You probably want to define your property with a default value
props: {
objectsProps: {
type: Array,
default() {
return [];
}
}
}
BTW:
I use a computed property on the component, because i don't know if it's recommended to do a v-for on the props.
No need for a computed property
This is what's happening in your code...
Vue allows specifying a prop of a specific data type like this:
props: {
foo: String
}
or with multiple valid types like this:
props: {
foo: [String, Number] // foo can be a `String` or a `Number`
}
The type array ([String, Number] in the example above) should not be empty:
props: {
foo: [] // invalid: missing types
}
This is how to fix it...
If you were attempting to enable type checking for the prop so that Vue enforced values of type Array, the correct syntax would be:
props: {
foo: Array
}
Or if you were trying to specify an empty array as the default prop value:
props: {
foo: {
default: () => []
}
}
You could even do both:
props: {
foo: {
type: Array,
default: () => []
}
}
demo
But i have no filter property in my main page or my component, so i don't get why...
Although I wasn't able to reproduce that error with the code shown in question, I'm guessing you have a third-party library/component that perhaps uses Array#filter on your array prop.
I had this empty section in my list :
<v-list-tile-action>
</v-list-tile-action>
And that was causing the filter error, i just had to delete it, thank you for your answers !
I am attempting to use the created lifecycle hook to set a data property on my component. Below is my single-file component. I'm currently seeing "TypeError: Cannot read property 'summary' of undefined" in the console when running this code. This tells me that the template is working with forecastData as the empty object declared in the data property rather than the populated object from created. When I remove the data property entirely I see TypeError: Cannot read property 'currently' of undefined. Clearly, I'm missing something basic here.
<template>
<div>
<p>
<router-link to="/">Back to places</router-link>
</p>
<h2>{{forecastData.currently.summary}}</h2>
<router-link :to="{ name: 'forecast' }">Forecast</router-link>
<router-link :to="{ name: 'alerts' }">Alerts</router-link>
<hr>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'CurrentWeather',
data () {
return {
forecastData: {}
}
},
created: function () {
this.$http.get('/api/forecast/boston').then((response) => {
this.forecastData = response.data;
}, (err) => {
console.log(err)
});
}
}
</script>
<style scoped>
</style>
You are setting the data asynchronously so it doesn't exist when the object is first mounted. When you try to access forecastData.currently.summary the currently property is undefined, which results in your error.
Use a v-if to avoid the error.
<h2 v-if="forecastData.currently">{{forecastData.currently.summary}}</h2>
Alternatively, define a null summary in your initialization.
data () {
return {
forecastData: {
summary: null
}
}
},