I have a component that renders it's template with for example a span that looks like:
<span>{{item.name}}</span>
the item is passed in as a property:
props: {
item: null
},
when the component is first mounted item is null, so when the render happens I get this in the logs:
[Vue warn]: Error in render: "TypeError: Cannot read property 'name'
of null"
If I create a computed property like this:
computed: {
name() {
if (this.item != null) {
return this.item.name
}
}
},
And then put name instead of item.name in the render it works fine, but is there a way to tell Vue to stop complaining about subproperties being null since it doesn't seem to care about root properties being null?
Maybe #LinusBorg knows?
That's not Vue-specific. Vue is simply warning you that you have a javascript TypeError. The error is being caused because you can't access a property of a null value in javascript.
I would just set the default value of your item prop to an empty object instead of null:
props: {
item: { type: Object, default: () => ({}) }
}
Related
I want to implement a props checker function, which is used to handle the situation with unexpected props problem. Below is an example,
<GrandFater :scope="scope" :id="id" v-bind="$attrs" #error="error" v-on="$listeners">
<Father>
<GrandSon />
<Father/>
<GrandFather />
Then, in the component GrandSon, I will pass these two props to a function to make further process, let's say authorize. Now, what I want to do is to implement a props checker function to check whether the two props is valid. For example, the prop scope is a string, but it cannot be missed and it also cannot be an empty string.
It cannot be missed means it must be declared in <GrandFather> component, such as
<GrandFater :id="id" v-bind="$attrs" #error="error" v-on="$listeners">
<Father>
<GrandSon />
<Father/>
<GrandFather />
In above example, the prop scope missed and I want to capture the error in my function.
class GrandFather extends Vue {
#Prop({ type: String }) id!: string;
#Prop({ type: String }) scope!: string;
mounted(){
if(propChecker(this)) return;
authorize(this);
}
}
In another JS file, I implement the propChecker like this:
export function parameterChecker(vm) {
let error: String = "";
switch (vm) {
case !vm.id:
error = "Parameter Id missing.";
break;
case !vm.id.trim():
error = "Parameter Id cannot be empty.";
break;
case !vm.scope:
error = "Parameter scope missing.";
break;
case !vm.scope.trim():
error = "Parameter scope cannot be empty.";
break;
default:
return false;
}
vm.$emit("error", error);
return true;
}
But now the question is if I miss a prop, such as scope, it will report an error:
[Vue warn]: Error in mounted hook: "TypeError: Cannot read properties of undefined (reading 'trim')".
Now the question is how could I implement my goal, and why this error will happen?
I would recommend using the prop validation (see the website here).
You can pass the props of your component using the props object which also contains object. Then you can either specify default parameters (if those aren't pass) or even use the required prop (which will throw an error if the props isn't pass).
All props are optional by default, unless required: true is specified.
Example :
props: {
myFirstProp: {
type: Object,
default: () => {scope: null},
required: true,
},
mySecondProp: {
type: String,
default: 'defaultValue'
},
myThirdProp: {
type: Boolean,
default: true
},
}
i want to pass a String to my child component like this, but previously i want to print it
this is my parent component
{{left.leftA}} // here show me 8
<CustomCard
:left="left.leftA"
export default {
name: 'Parent',
data() {},
setup() {
onMounted(async () => {
const answer = await getData(name)
left.value = answer.response //{leftA:'A', leftB:'B'...}
})
and in my child component i have this declaration
export default {
name: 'CustomCard',
props: {
left: {
type: String,
required: true,
},
i am getting this warning:
[Vue warn]: Invalid prop: type check failed for prop "left". Expected String with
value "undefined", got Undefined
Does it have something to do with how I am loading the data? is it ok to use onMounted?
This is happening because the initial value for value is null. So, on initial render it throws the warning, but upon another render it has the correct prop type (a string) and renders correctly.
You have 3 options. Allow '' as an option on the prop or don’t render the component until you have the correct data or make use of computed Property.
Option-1
{{left.leftA}} // here show me 8
<CustomCard
:left="left.leftA ? left.leftA : ''"
Option-2
{{left.leftA}} // here show me 8
<CustomCard v-if="loaded"
:left="left.leftA"
and in onMounted(}
onMounted(async () => {
const answer = await getData(name)
left.value = answer.response //{leftA:'A', leftB:'B'...}
// Set the loaded flag as true here. Also make sure its set as false inside the setup()
})
Option-3
{{left.leftA}} // here show me 8
<CustomCard
:left="sendVal"
In computed....
computed: {
sendVal() {
if(left && left.left1) return left.left1;
return '';
}
}
I'm using Vue in vanilla JS and have a property defined in my data of type string which looks like this
data() {
return {
DimensionSetting: { type : String }
}
}
I have an element in my template that I want to toggle off when a value is passed into DimensionSetting however I can't figure out how I need to check for it in the v-if logic. I tried v-if="!this.DimensionSetting" and v-if="this.DimensionSetting === undefined" and v-if="this.DimensionSetting === null". None of these make the element visible when the value is empty. What do I need to do to properly check that kind of property?
It looks like you're incorrectly mixing a data property declaration with a props declaration.
If DimensionSetting is supposed to be a public property that receives values from a parent component, it should be declared under props:
export default {
props: {
DimensionSetting: {
type: String,
}
}
}
On the other hand, if DimensionSetting is supposed to be a local property, private to the component itself, then it should be returned from data(). There is no type field like there is for props declarations:
export default {
data() {
return {
DimensionSetting: ''
}
}
}
In either case, using the ! operator on the prop should be enough to check for an empty string:
<p v-if="!DimensionSetting">Empty</p>
demo
try adding,
data(){
return{
DimensionSetting: { type : String ,default:false}
}
}
and then v-if="!DimensionSetting"
I have a error at my vue project.I use computed to return a object.
computed: {
getOpLog() {
if (this.product_menu) {
this.product_menu.forEach(opLogItem => {
if(opLogItem.id === 'menu_item_oplog') {
return opLogItem;
}
});
}
}
},
and my debugger shows that I have the right return object.
But when i run it in brower, it just not work.
[Vue warn]: Error in render: "TypeError: Cannot read property 'hidden' of undefined"
Here is my html.
<el-menu-item v-if="getOpLog.hidden" :id="getOpLog.id">
...
</el-menu-item>
But when I use this
getOpLog() {
if (this.product_menu) {
return this.product_menu[8]
}
}
It work.I want to know how can i fix this.Thx
When your if condition inside the getter is false i.e. if (this.product_menu), then getter will return undefined object. And thus, Vue.js complains.
As a simple remedy, add an extra check in v-if like:
<el-menu-item v-if="getOpLog && getOpLog.hidden" :id="getOpLog.id">
...
</el-menu-item>
Further, using return inside the forEach function of an array doesn't really cause a return from actual getter function. It is just returning from the inner arrow function. You will need to modify your code using Array.prototype.find method:
computed: {
getOpLog() {
if (this.product_menu) {
const item = this.product_menu.find(opLogItem => {
return opLogItem.id === 'menu_item_oplog';
});
return item;
}
}
};
But, you still should have v-if check for getOpLog in case find method returns undefined value.
I am not sure why I get a Vue warning when accessing nested object.
{{ user.area.name }}
[Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"
TypeError: Cannot read property 'name' of undefined
Just accessing the object has no warning.
{{ user.name }}
Any advice?
Totally guessing here but lets see if I'm right...
Say you've got something like this in your component / Vue instance data initialiser...
data () {
return {
user: {}
}
}
and you then populate that object asynchronously, eg
mounted () {
setTimeout(() => { // setTimeout is just an example
this.user = {
...this.user,
area: {
name: 'foo'
}
}
}, 1000)
}
If your template has
{{ user.area.name }}
when it initially renders before the asynchronous task has completed, you will be attempting to access the name property of area which is undefined.
Example ~ http://jsfiddle.net/tL1xbmoj/
Your options are...
Initialise your data with a structure that won't cause errors
data () {
return {
user: {
area: {
name: null
}
}
}
}
Example ~ http://jsfiddle.net/tL1xbmoj/1/
Use conditional rendering to prevent the error
<span v-if="user.area">{{ user.area.name }}</span>
Example ~ http://jsfiddle.net/tL1xbmoj/2/
Your user doesn't contain an area, so when you try to read that, it's undefined. You're not allowed to use the . operator on things that are undefined, so when you do .name on that, you get the error that you got.
You could also use a ternary operator {{ user.area ? user.area.name : "" }}