How can I get a hight of v-card-title vuetify element? - vue.js

I have the following code and I would like to get the height of v-card title element?
<v-card-title class="purple lighten-2">
<v-icon dark size="42" class="mr-4"> fas fa-egg </v-icon>
<h3 class="white--text font-weight-medium flex-nowrap">
{{ dishes[dishesIndexList[0]].dish_name }}
</h3>
</v-card-title>
How can I do it? I tried to add ref="cardTitleHeight" to v-card title and then when the elements are mounted I can get this.$refs and the cardTitleHeight ref I added is listed as part of $refs objects but when I try to get it using this.$refs.cardTitleHeight I get undefined (I need to get this element first to get its hight).
I suppose that it is because v-card-title is an external component.
How is it possible to get v-card-title height? I would be grateful for advice.

You have the answer in your question
when the elements are mounted
The height of this element will be defined after the component has been mounted.
in your script you can try :
mounted() {
console.log(this.$refs.cardTitleHeight); //.style.height or lineHeight
},
Note that mounted does not guarantee that all child components have also been mounted. If you want to wait until the entire view has been rendered, you can use vm.$nextTick inside of mounted.
More about the mounted life cycle hook.

Related

Using v-model inside nested v-for

I am trying to use multiple carousel components inside card components with nested v-for loops but I’m having trouble figuring out the correct way to assign the carousel v-model so that it’s unique and doesn’t update all the carousels when the slide is changed which is what I currently have,
Here is the code I have so far:
<q-card
v-for="(item, index) in inventory"
:key="index"
style="width: 20rem;"
>
<q-card-section
class="q-pa-none text-white"
>
<q-carousel
animated
arrows
navigation
infinite
style="height: 15rem;"
v-model="slide" // What should this be assigned so that
>
<q-carousel-slide
v-for="(image, index) in item.images"
:key="index"
:name="index" //It works with the slide name and only updates the respective q-carousel
:img-src="image.url"
>
</q-carousel-slide>
</q-carousel>
</q-card-section>
</q-card>
slide is simply a data prop assigned to 0, this works but when I change the slide of one carousel all of the carousels change too.
Hopefully this makes sense, It’s a bit hard for me to explain it but let me know anything that needs clarification
Edit: Dropped the code in codepen here is the link: https://codepen.io/launchit-studio/pen/jOVrKzQ
The issue I am having is that the v-model affects all of the carousel slides not just the one that is clicked. I understand this is because the slide prop is shared by all the carousels but I am not sure of what to use in order for it to be 'independent'
Instead of using a single model slide for all the slides, use an array of models. (An object would work too).
data() {
return {
slide: 1, ❌
activeSlides: [] ✅
}
}
The index of the carousel in the v-for will also be used as the index in the array:
<q-carousel
animated
arrows
navigation
infinite
style="height: 15rem;"
v-model="activeSlides[index]"
>
Since each carousel's model needs to start at 1, you can initialize activeSlides accordingly:
created() {
const numCarousels = this.inventory.length;
this.activeSlides = Array(numCarousels).fill(1);
},
Here is the updated CodePen.

Passing slots through from Parent to Child Components

I have built a user-defined component (async-select) on top of another component (vue mutliselect) like this:
https://jsfiddle.net/2x7n4rL6/4/
Since the original vue-multiselect component offers a couple of slots, I don't want to loose the chance to use them. So my goal is to make these slots available from inside my custom component. In other words, I want to something like this:
https://jsfiddle.net/2x7n4rL6/3/
But that code oes not work.
However, if I add the slot to the child component itself, it works just fine (which you can see from the fact that options become red-colored).
https://jsfiddle.net/2x7n4rL6/1/
After surfing the web, I have come across this article, but it does not seem to work
Is there any way in VueJS to accomplish this ?
Slots can be confusing!
First, you need a template element to define the slot content:
<async-select :value="value" :options="options">
<template v-slot:option-tmpl="{ props }">
<div class="ui grid">
<div style="color: red">{{ props.option.name }}</div>
</div>
</template>
</async-select>
Then, in the parent component, you need a slot element. That slot element itself can be inside of another template element, so its contents can be put in a slot of its own parent.
<multiselect
label="name"
ref="multiselect"
v-model="localValue"
placeholder="My component"
:options="options"
:multiple="false"
:taggable="false">
<template slot="option" slot-scope="props">
<slot name="option-tmpl" :props="props"></slot>
</template>
</multiselect>
Working Fiddle: https://jsfiddle.net/thebluenile/ph0s1jda/

Why do not undeclared props pass to the components's root element?

I made a wrapper around Vuetify's 'v-dialog' component named 'Modal' and wanna pass props through it:
<template>
<v-dialog
class="modal"
max-width="600"
v-on="vDialogListeners"
>
<v-card>
<v-card-title class="headline">
<slot></slot>
</v-card-title>
<v-card>
...
</v-dialog>
</template>
I use it like this ('value' prop):
<Modal
:value="showModal"
:confirm="true"
#close="onModalClose"
#click:outside="onModalClose(false)">
Are you sure you'd like to log out?
</Modal>
I know about $attrs and it works if I bind it explicitly, i.e, v-bind="$attrs" within <v-dialog> opening tag.
My question: why doesn't work it by default, that's without explicit v-bind="$attrs", if <v-dialog> is the component's root element and should accept all props undeclared in the component, or I'm wrong and misunderstand this part of documentation?
I used to think that v-bind="$attrs" is only used in case inheritAttrs: false in order to pass udeclared props to a component's not-root element (a nested one).
I have a guess: maybe, it only concerns the components root html element (e.g., input tag) by default.
It seems I figured out the proper usage of it. By default, it adds these $attrs to the DOM element as attributes. By explicit binding, I can pass them to the necessary child component. By setting inheritAttrs = false, I cancel the default behavior of adding attributes to the DOM element. Thus, I can combine these options to get the suitable behavior.

Pass a button with click handler via slot to recursive child component

I've got a page template with the following code part:
<nested-draggable v-bind:list="list" v-bind:selected="selected" v-bind:group="dragGroup">
<slot>
<v-icon v-on:click="$root.$emit('click', el)" small v-if="allowcreate" style="float: right">mdi-plus</v-icon>
</slot>
</nested-draggable>
the sub component ("nested-draggable.vue") for the recursion looks like this:
<template>
<ul class="tree">
<draggable
class="dragArea"
tag="li"
v-for="el in list"
v-bind:elementdata="el"
v-bind:key="el._id"
v-bind:list="list_empty"
v-bind:selected="selected"
v-bind:group="group"
v-on:add="add"
>
<span v-bind:class="{'selected' : el._id === selected._id}" v-on:click="elemClicked(el)">{{ el.title }}</span>
<slot></slot>
<!-- render children of the current iterated element -->
<nested-draggable
v-bind:list="el.children" v-bind:selected="selected" v-bind:group="group">
<!--<slot></slot>-->
</nested-draggable>
</draggable>
</ul>
</template>
so I'd like to have the click event from the button within the passed slot emited with the current iteration's var "el" when the "plus" button is clicked, but within the slot the "el" var that is used within the iteration at the nested-draggable component can not be accessed. Vue tells that there is no "el" reference when trying to emit. (Throwing this error: https://pastebin.com/8bNwMcDr)
So how can I access the recursive data within the passed slot? How do I have to define my slot when passing it?
The only solution I found is putting the button/event-link directly into the nested-draggable component (not as slot) but I think to be clean and write a nice separated component, this would not belong into the nested draggable component, but in its parent.
You don't need to pass your event from the template because you can get in your method anyways. This should help you out.

Vue slot activator during tooltip is re-rendering my v-icon

I am trying to put a tooltip on a v-icon who randomly gets assigned a color. Every time I mouse over the v-icon, the color changes. I only want the color to be set one time. I do not want the color to change every time the mouse is hovered over the v-icon. Any suggestions?
<v-tooltip bottom>
<template #activator="{on}">
<v-icon v-on="on" :color="getRandomColor()">mdi-close</v-icon>
</template>
<span>Some Tooltip text</span>
</v-tooltip>
I got around this by making a color array in the data: section of Vue and generating the random colors there. Then, I just call that specific array index in color. Something like this:
data() {
return {
rColors: [getRandomColor(), getRandomColor()],
}
}
<v-icon v-on="on" :color="rColors[0]">mdi-close</v-icon>
Is there a way to avoid doing this by putting a keyword in the previous code?
Something like
v-on:once="on" ?