I'm getting this super confusing Vue warning and I can't figure it out:
[Vue warn]: Property "me" was accessed during render but is not defined on instance.
at <UserReputation user= {reputation: {…}, _id: '638f81dbb288267e6340ddbc', username: 'artsborba'…} class="mt-1" >
...
Here on StackOverflow I can find more topics with this warning, but seems each one is a different case, and mine is just not making sense! My vue version is ^3.1.0, vuetify ^3.1.0 and vite ^2.5.4.
My component looks like:
// MyComponent.vue
<v-menu location="end" location-strategy="connected">
<template #activator="{ props }">
<div
v-bind="props"
class="user-info-container cursor-pointer"
>
<UserAvatar
:user="me"
/>
<div v-if="me" class="user-data">
<div class="username-row">
{{ me.username }}
<AppIcon
icon="downward-arrow"
color="primary"
class="user-menu-icon"
:class="{ 'is-active': props['aria-expanded'] === 'true' }"
/>
</div>
<!-- HERE WE HAVE THE WARNING SOURCE -->
<UserReputation :user="me" class="mt-1" />
</div>
</div>
</template>
...
</v-menu>
In the same component I have the me set as a prop:
props: {
me: {
validator: prop => typeof prop === 'object' || prop === null,
required: true
}
},
Now, please notice that in the same component I have another one using this me pro (<UserAvatar :user="me"...>), which doesn't trigger this warning. Only the <UserReputation... component usage does! If I comment out the <UserReputation... tag, the warning goes away.
I already tried placing this me as a computed value instead of a prop, directly inside MyComponent.vue (it comes from a Pinia store) and many other structures with no success. Hopefuly someone can help on this! Thanks in advance.
Maybe you are accesing at me property inside your UserReputation component, but in the parent you are passing me to user prop, like this :user="me", so... you need to access to user prop instead me prop inside UserReputation component.
If this answer doesn't resolve the question, please share us the structure of UserReputation component.
hello i just joined you,
I want to use heroicons dynamically with vue 3 js,
What I want to do is on the Home page you see below; atrribute I want that icon to be called according to the icon name I wrote.
For example in Home.vue
There are 2 examples available.
Please I would be happy if you take into account that I am new here and have little experience with vue js while writing an answer. Thank you from now.
This is what I want to do, it doesn't have to be in a .vue template, it can be given as an example as .js.
heroicons
<my-icon svgIcon="heroicons_outline:menu"></my-icon>
<my-icon svgIcon="heroicons_solid:menu"></my-icon>
<template>
<my-icon svgIcon="heroicons_outline:menu"></my-icon>
<my-icon svgIcon="heroicons_solid:menu"></my-icon>
</template>
<script>
import MyIcon from "./MyIcon";
export default {
name: "Home",
components: {MyIcon},
};
</script>
MyIcon.vue
<template>
<label class="block font-bold text-md text-gray-700">
<svgIcon></svgIcon>
</label>
</template>
<script>
import {svgIcon} from '#heroicons/vue/outline'
import {defineComponent} from 'vue';
export default defineComponent({
props: ['svgIcon']
})
</script>
I have a single file component called confirm-document that looks something like this:
Sandbox
<template>
<v-dialog>
<template v-slot:activator="{ on }">
<v-btn v-bind="$attrs" :class="activatorClass" v-on="on">{{
title
}}</v-btn>
</template>
<v-card>
<v-card-title>{{ title }}</v-card-title>
<v-card-text><slot></slot></v-card-text>
</v-card>
</v-dialog>
</template>
<script>
export default {
name: "ConfirmDocument",
props: {
title: String,
activatorClass: {},
},
};
</script>
So when I then use this component like:
<ConfirmDocument
class="useless-class"
activator-class="mt-4 ml-n4"
title="Consent"
> Document Content </ConfirmDocument>
Sandbox
The classes get applied to the v-dialog, which ends up as an invisible div with nothing inside and both the activator and modal attached as sibling nodes.
Since this is mainly a wrapper component to provide a consistent UI, I actually only need for the activator to be positionable. So I want to pass the class and style props to the v-activator.
The activator-class prop that I have declared actualy works fine. But I am very curious if there a way to change the element to which the component's class and style attributes are bound, so that I can use class instead?
This is fixed in Vue.js v3 ref
For Vue.js v2, you can try this
Check v-bind and attrs computed property below
<template>
<v-dialog>
<template v-slot:activator="{ on }">
<v-btn v-bind="attrs" v-on="on">{{
title
}}</v-btn>
</template>
<v-card>
<v-card-title>{{ title }}</v-card-title>
<v-card-text><slot></slot></v-card-text>
</v-card>
</v-dialog>
</template>
<script>
export default {
name: "ConfirmDocument",
inheritAttrs: false, // <- added just for safety
props: {
title: String,
},
computed: {
attrs() {
const attrs = { ...self.$attrs }
// adding class and style for `v-bind`
attrs.class = self.$vnode.data.staticClass
attrs.style = self.$vnode.data.staticStyle
return attrs
}
}
};
</script>
Explanation - In Vue.js version 2.x.x, $attrs does not include class and style (ref) but there are many scenarios in which we wanted to pass on all the props along with class and style into another component so, $attrs should have class and style in it which they did add in version 3 of vue.js.
There is a detailed discussion on this topic on github do check it out for more details.
For version 2, what we wanted to achieve is that class and style can be passed to another component. We can pull it off by getting the class [as string] and style [as object] from the current component node i.e. vnode and pass it on to the other component using v-bind.
Now, you can pass props along with class and style into another component inside ConfirmDocument directly from the parent (or caller) component
What's about simple using props to handle this?
<template>
<v-dialog>
<template v-slot:activator="{ on }">
<v-btn :class="btnClass" v-on="on">Read {{ title }}</v-btn>
</template>
<v-card>
<slot></slot>
</v-card>
</v-dialog>
</template>
<script>
export default {
props: {
btnClass: { type: String },
title: { type: String }
}
}
</script>
and using the component:
<confirm-document
btn-class="mt-0 mb-0"
title="Privacy Policy"
>
Lorem ipsum dolor sit amet
</confirm-document>
I think you can use the inheritAttrs: false property. What it does it to make sure that attributes are not applied automatically to the root element and it lets you choose where to apply them instead.
<template>
<v-dialog>
<template v-slot:activator="{ on }">
<v-btn v-bind="buttonAttrs" >Read {{ title }}</v-btn>
</template>
<v-card>
<slot></slot>
</v-card>
</v-dialog>
</template>
<script>
export default {
inheritAttrs: false,
props: {
title: {type: String},
},
computed: {
buttonAttrs () {
// select which attrs to apply
const { title, ...rest } = this.$attrs;
return rest;
}
}
}
</script>
A working (and a bit cluttered) example can be found here.
I'm using a data table from Vuetify:
<v-data-table
:ref="`sortableTable${index}`"
class="items-table-container"
:headers="headers"
:items="category.items"
hide-default-footer>
...custom rows
</v-data-table>
I noticed that when adding a new item to the table, it wasn't appearing. I verified that the items I'm passing it have 11 items, however the table is only displaying 10 max.
When I looked at the wrapper surrounding the table, I noticed that it had:
overflow-x: auto;
overflow-y: hidden;
however, I'm unable to override it for some reason. I've tried adding the height prop but nothing seems to work.
How can I give the table an auto height, so that it expands no matter how many rows are in the table?
This issue is happening because you have removed default footer using hide-default-footer, but the pagination is still enabled. Pagination is by default set to show only 10 items per row. You can easily fix this by simply adding disable-pagination options, which disables pagination completely and then you can see all items after 10th index also.
<v-data-table
:ref="`sortableTable${index}`"
class="items-table-container"
:headers="headers"
:items="category.items"
hide-default-footer
disable-pagination>
DEMO:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
headers: [{text:"Dessert (100g serving)",align:"start",sortable:!1,value:"name"},{text:"Calories",value:"calories"},{text:"Fat (g)",value:"fat"},{text:"Carbs (g)",value:"carbs"},{text:"Protein (g)",value:"protein"},{text:"Iron (%)",value:"iron"}],
desserts: headers=[{name:"Frozen Yogurt",calories:159,fat:6,carbs:24,protein:4,iron:"1%"},{name:"Ice cream sandwich",calories:237,fat:9,carbs:37,protein:4.3,iron:"1%"},{name:"Eclair",calories:262,fat:16,carbs:23,protein:6,iron:"7%"},{name:"Cupcake",calories:305,fat:3.7,carbs:67,protein:4.3,iron:"8%"},{name:"Gingerbread",calories:356,fat:16,carbs:49,protein:3.9,iron:"16%"},{name:"Jelly bean",calories:375,fat:0,carbs:94,protein:0,iron:"0%"},{name:"Lollipop",calories:392,fat:.2,carbs:98,protein:0,iron:"2%"},{name:"Honeycomb",calories:408,fat:3.2,carbs:87,protein:6.5,iron:"45%"},{name:"Donut",calories:452,fat:25,carbs:51,protein:4.9,iron:"22%"},{name:"KitKat",calories:518,fat:26,carbs:65,protein:7,iron:"6%"},{name:"Jelly bean",calories:375,fat:0,carbs:94,protein:0,iron:"0%"},{name:"Lollipop",calories:392,fat:.2,carbs:98,protein:0,iron:"2%"},
{name:"Ice cream sandwich",calories:237,fat:9,carbs:37,protein:4.3,iron:"1%"},{name:"Eclair",calories:262,fat:16,carbs:23,protein:6,iron:"7%"},{name:"Cupcake",calories:305,fat:3.7,carbs:67,protein:4.3,iron:"8%"},
{name:"Ice cream sandwich",calories:237,fat:9,carbs:37,protein:4.3,iron:"1%"},{name:"Eclair",calories:262,fat:16,carbs:23,protein:6,iron:"7%"},{name:"Cupcake",calories:305,fat:3.7,carbs:67,protein:4.3,iron:"8%"}],
}
},
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout column>
<v-data-table :headers="headers"
:items="desserts"
class="elevation-1"
hide-default-footer
disable-pagination
dense>
</v-data-table>
</v-layout>
</v-container>
</v-app>
</div>
The default item count per page is 10. use -1 instead of 10. add this line.
:items-per-page="-1"
You should add disable-pagination in your v-data-table tag and it should look something like this
<v-data-table \*more items come in here *\ disable-pagination>
then Vuetify DataTable will render out all the data in one continual table.
Assume that I have three tabs together,content in each tab are fetched via core-ajax
<core-ajax auto url="http://example.com/tab.json" handleAs="json"
response="{{response}}"></core-ajax>
<paper-tabs id="tabs" selected="{{response[0].name}}" flex >
<template repeat="{{mytab as t}}">
<paper-tab name="{{t.name}}">{{t.name}}</paper-tab>
</template>
</paper-tabs>
Polymer({
responseChanged:function(response){
this.mytab= this.response;
console.log(this.mytab[0].name);
}
});
codes above display normal,but what is confusing me is that,when i click the other two tabs other than the first one,the first one tab name(i.e. content) changes accordingly to the name of which tab was clicked.i can't get that ,can anyone explain to me ?
Thanks
Peng
I find a solution to solve this problem,but i don't know if this is the right way or the best:
<core-ajax auto url="http://example.com/tab.json" handleAs="json"
response="{{response}}"></core-ajax>
(changed)
<paper-tabs id="tabs" selected="{{defaulttab}}" flex >
<template repeat="{{mytab as t}}">
<paper-tab name="{{t.name}}">{{t.name}}</paper-tab>
</template>
</paper-tabs>
Polymer({
responseChanged:function(response){
this.mytab= this.response;
this.defaulttab = this.response[0].name;(added)
console.log(this.mytab[0].name);
}
});
This works as expected.