Why can't I set <v-app-bar> height to auto? - vuejs2

Very simple code.
<div>
<v-app-bar
app
flat
>
<v-app-bar-title>
Page Title
</v-app-bar-title>
</v-app-bar>
<v-container fluid>
<v-card
height="400"
outlined
flat
>
<v-card-title>
Card Title
</v-card-title>
</v-card>
</v-container>
</div>
Everything works as expected, but if I add height="auto" to my <v-app-bar> this happens.
Looks like <v-main> is no more calculated correctly. How can I avoid this issue?

Answering the question "why you can't set <v-app-bar> height to auto" you need to deep dive into Vuetify sources.
So, basically <v-app-bar> is the extension of <v-toolbar> component. Looking at the sources, we can find that height style prop is calculated by this code:
genContent () {
return this.$createElement('div', {
staticClass: 'v-toolbar__content',
style: {
height: convertToUnit(this.computedContentHeight),
},
}, getSlot(this))
},
We are interested in how this.computedContentHeight calculates. Look at this code:
computedContentHeight (): number {
if (this.height) return parseInt(this.height)
if (this.isProminent && this.dense) return 96
if (this.isProminent && this.short) return 112
if (this.isProminent) return 128
if (this.dense) return 48
if (this.short || this.$vuetify.breakpoint.smAndDown) return 56
return 64
},
The answer is: every time when you pass some string into height prop, Vuetify tries to convert it into integer value. You are trying to pass auto value, but parseInt("auto") is NaN. That's why you can't pass this value. I think, it is not explained well in Vuetify docs.
If you are really want to set height:auto, you can set style="height: auto" for your <v-app-bar> component. But, as #yoduh already said, possibly it is not what you want.

With height="auto", v-main no longer knows how much padding to use to offset your page content from the app-bar because it can't know what height=auto will end up being in pixels ahead of time, so v-main ends up at the top of the viewport behind the app-bar. To avoid the issue, just don't use height="auto". If you want a smaller app-bar, vuetify provides the dense prop that you can use, or you can always specify a specific height pixel value

Related

How to add image into v-text-field?

I have been trying to add image inside v-text-field, but it is causing an issue when I add it moves label to a bit of right side?
<v-text-field
ref="phone"
v-model="phone"
dense
outlined
disabled
color="black"
:rule="[requiredRule]"
:label="$t('10')"
>
<template #prepend-inner>
<v-img style="margin: auto 0" max-height="25" max-width="30" src="/images/KW.png"> </v-img>
</template>
</v-text-field>
as you can see label PHONE moves to right side it isn't staying on its place, I tried to add margin-top but didn't fix it.
This looks like an undocumented feature, which explains why the behaviour may be unexpected.
The cause of the seems to me is that the input calculates the width of the slot content at the time of rendering, which due to a race condition may resolve before or after the image is rendered. That's why if you render multiple times, you may not always see it behaving this way.
To get around it, I thing you should be able to wrap the image with another element of fixed width. (<div style="width:30px">)
<v-text-field
ref="phone"
v-model="phone"
dense
outlined
label="My Label"
>
<template #prepend-inner>
<div style="width:30px">
<v-img style="margin: auto 0" max-height="25" max-width="30" src="/images/KW.png"/>
</div>
</template>
</v-text-field>

How to reduce the width of v-switch

The v-switch seems to always take 100% width, as seen below. Is there a way to reduce its clickable area to the minimum? Thanks!
clickable v-switch in the blank: https://vuetifyjs.com/en/components/switches/#usage
I suggest that you read this link from vuetify documentation. the reason that v-switch is continuing to the right of page is that v-container above it. you can modify the layout with vuetify grid system like below:
a Vue js page
<template>
<div class="about">
<v-container
class="px-0"
fluid
>
<v-row>
<v-col md="4">
<v-switch
class="my-border"
v-model="switch1"
:label="`Switch 1: ${switch1.toString()}`"
></v-switch>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script>
export default {
data () {
return {
switch1: true,
}
},
}
</script>
<style scoped>
.my-border {
border: 1px solid #000;
}
</style>
You can add d-inline-block class to v-switch which will reduce the div width to the content's max width.
The alternative, as the previous answer explained, is to wrap it in a row/column. Either don't set a column value or set it to a number because col-auto may cause it to be more narrow than desired and cause label to go over multiple lines.

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

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.

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" ?

How to fill the width of the content in vuetify

What I want is that to fill the width of the entire mobile screen with vuetify
with this code :
<v-content>
<router-view>
<v-container fluid></v-container>
</router-view>
</v-content>
the router view has a margin on both left and right side
and that bottom-nav is already fitted on the screen and I won't be dragging the screen to show the bottom-nav
I needed to dynamically remove padding only on mobile, this works for me:
<v-container :class="{'px-0': $vuetify.breakpoint.xsOnly }">
<router-view> </router-view>
</v-container>
There is not much documentation that I could find as of now, but looking at the code I found these:
// Breakpoint ranges.
xsOnly,
smOnly,
smAndDown,
smAndUp,
mdOnly,
mdAndDown,
mdAndUp,
lgOnly,
lgAndDown,
lgAndUp,
xlOnly,
you can also try this, vuetify has helper classes to set padding and margin
<v-container fluid class="pa-0 ma-0">
</v-container>
v-container creates a div with the class container. This class gives your div padding on all sides. (The amount changes depending on the viewport breakpoint; it's 2px for xs, 24px for xl). If you include the below in your css, your side padding should go away.
.container {
padding: 0!important
}