Changing the Vuetify carousel height - vue.js

Is it possible to reduce the height of a <v-carousel>? I saw in the documentation that they were working on it, but has it been implemented yet? If not is there a work around? I'm just trying to set a max height.

You can set auto height of it:
<v-carousel height="auto">

There's no need to use CSS neither important on it.
You can use one prop to change the height:
Name: height
Default: 500
Type: number | string
Sets the component height
Eg.
<v-carousel height="500px">
<v-carousel-item
v-for="(item,i) in items"
:key="i"
:src="item.src"
></v-carousel-item>
</v-carousel>

In your main vue component or in the component where you have the v-carousel add a css rule:
.carousel {
height: 200px !important;
}
Add !important if it's not working without it
If you're putting this rule in the main component make sure the <style> tag doesn't have the word scoped in it

If you want dynamic height of v-carousel based on image, for example.
You can use something like this:
example:
<v-carousel :style="{'height': this.carouselHeight}">
<v-carousel-item v-for="(item, index) in items" :key="index" style="height: auto" :src="item.image"></v-carousel-item>
</v-carousel>
set data prop:
data () {
return {
carouselHeight: 0
{
}
create method:
getCarouselHeight () {
var item = document.getElementsByClassName('v-image__image--cover')
this.carouselHeight = item[0].clientHeight + 'px'
}
call method on mounted:
mounted () {
this.getCarouselHeight()
}

Related

Vue Element UI dynamically changes el-select color

I tried to modify el-select to match the color of el-option.
The methods I search on the Internet always require me to modify the style scoped . It is a static method and cannot be changed dynamically.
My expectation is when I select "WIP" in the options, it will become a yellow label in el-select according to the color in the options.
The following is a rough demo I created in Codesandbox.
https://codesandbox.io/s/dynamically-change-el-select-color-based-on-status-v0u8d?file=/src/views/Editor.vue
Your kind assistance will be greatly appreciated, thank you very much.
You could set the class of the el-select based on that you could color the input value based on the selected value
<el-select
v-model="scope.row.status"
:class="getStatusColorClass(scope.row.status)"
placeholder="Select"
>
<el-option
v-for="(status, index) in statusList"
:key="index"
:label="status.name"
:value="status.id"
>
<span :style="{ color: status.color }">{{ status.name }}</span>
</el-option>
</el-select>
JS:
methods: {
getStatusColorClass(id) {
if (!id) {
return {};
}
return this.statusList.find(status => status.id === id).name;
}
}
SCSS:
<style lang="scss">
.Approved input {
color: #00A86B;
}
.Retake input {
color: #ED2939;
}
.WIP input {
color: #FCE205;
}
</style>
After a ton of research, finally I found the solution.
The following is a rough demo I created in Codesandbox.
https://codesandbox.io/s/dynamically-change-el-select-color-based-on-status-v2-od8gn?file=/src/views/Editor.vue
I'm not sure if this is the best method, but this method has solved my problem. If you have a better solution, welcome to provide here.
Thank you very much!

set image height based on breakpoint

Vuetify's image component ( https://vuetifyjs.com/en/components/images/ ) provides a height prop. How can I keep that height variable based on the current breakpoint? It would be nice to have something like this
<v-img
:height="img.height.xs"
:sm="img.height.sm"
:md="img.height.md"
:lg="img.height.lg"
:xl="img.height.xl">
</v-img>
Do I have to do it with a calulated property or is there a way to solve it with HTML only? By that, I mean I'm looking for a solution like the TailwindCSS approach ( https://tailwindcss.com/docs/height/#responsive )
<div class="h-8 sm:h-12 md:h-16 lg:h-20 xl:h-24"></div>
I created a code snippet for example purposes
https://codepen.io/dsm98861/pen/qBbXomN?editable=true&editors=101%3Dhttps%3A%2F%2Fvuetifyjs.com%2Fen%2Fcomponents%2Fcards%2F
Vuetify has its own predefined and overridable breakpoints.
I think, the most correct way to solve your problem is to use computed props. According to your codepen, it should be something like this:
<div id="app">
<v-app id="inspire">
<v-card
class="mx-auto"
max-width="400"
>
<v-img
class="white--text align-end"
src="https://cdn.vuetifyjs.com/images/cards/docks.jpg"
:height="imageHeight"
></v-img>
</v-card>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
computed: {
imageHeight () {
switch (this.$vuetify.breakpoint.name) {
case 'xs': return '200px'
case 'sm': return '400px'
case 'md': return '600px'
case 'lg': return '800px'
case 'xl': return '1000px'
}
},
}
})
If you are really want to solve it HTML-only, you could set height prop this way:
<v-img
class="white--text align-end"
src="https://cdn.vuetifyjs.com/images/cards/docks.jpg"
:height="$vuetify.breakpoint.xs
? '200px'
: ($vuetify.breakpoint.sm
? '400px'
: ($vuetify.breakpoint.md
? '600px'
: ($vuetify.breakpoint.lg
? '800px'
: '1000px'
)
)
)"
></v-img>
You may be able to come up with a more elegant and suitable solution after reading the article about breakpoints in Vuetify docs.
Why do you want to use HTML only?
Don't forget that use can change window size and you need to react on it dynamically. Which is not possible with plain HTML. This is possible with script but it's complicated. Using media queries is easy and proper tool.
I don't know what CSS pre-processor you are using. But for SASS you can use conditional styles based on breakpoint (compiled to media queries)
#media #{map-get($display-breakpoints, 'md-only')}
img
width: 200px
#media #{map-get($display-breakpoints, 'sm-and-down')}
img
width: 100px

VueJS - Is there a way to conditionally apply a transition?

What I would like to do is create an alert box component with a custom reveal transition that is optional, something like this (edited for brevity):
<template>
<transition v-if="withTransition">
<b-alert v-bind="this.$attrs" />
</transition>
</template>
I will have a withTransition prop that ideally will conditionally render only the transition effect, and not affect the rendering of the alert box.
v-if and v-show won't work because those properties would show and hide the alert component as well. Plus, AFAIK <transition> does not render as a DOM element, so I'm not sure how that could be conditionally rendered, if at all.
Any suggestions?
You can use dynamic transitions and bind to a transition name (using a computed property) that does nothing when you want the effect disabled.
For example...
new Vue({
el: '#app',
data: () => ({ withTransition: true, show: false }),
computed: {
computedTransition () {
return this.withTransition && 'fade'
}
}
})
.alert {
background-color: #f99;
border: 1px solid #f66;
padding: 1rem;
}
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<div id="app">
<p>
<label>
With transition:
<input type="checkbox" v-model="withTransition"/>
</label>
</p>
<p><button type="button" #click="show = !show">Toggle alert</button></p>
<transition :name="computedTransition">
<p class="alert" v-if="show">Something happened</p>
</transition>
</div>
Use an inline ternary condition
If you just need to quickly check against a variable, this is an option:
<transition :name="someVariable == 'someValue' ? 'myTransitionA' : 'myTransitionB'">
someVariable could be anything (prop, data, computed, method...).
Set a transition name (e.g.'myTransitionB') to just an empty string '' if you wanted no transition at all for a particular condition.
I use this technique to toggle transitions based on different UI contexts (e.g. mobile vs desktop). For example, I want control bars to slide in-and-out in mobile, but I want them to be static on desktop.

How to disable transition-group only on page load?

I have a transition-group that renders a div, and within that is a component with a v-for attribute that renders several items. I then have a button that adds a new item to the beginning of the array. That transition works perfectly.
The only thing I don't like, is that the entire list loads with the transition on page load, and I'd like to disable it only on page load. I've searched Stack and Google but couldn't find a way. Is there a way to do this, so that transitions still works on button click, but is disabled for page load?
<transition-group
name="item-list"
tag="div">
<item-row
v-for="item in items"
:key="item.id"
:item="item" />
</transition-group>
.item-list-enter-active,
.item-list-leave-active,
.item-list-move {
transition : 250ms cubic-bezier(0.59, 0.12, 0.34, 0.95);
transition-property: opacity, transform;
}
.item-list-enter {
opacity : 0;
transform: translateX(50px) scaleY(0.5);
}
.item-list-enter-to {
opacity : 1;
transform: translateX(0) scaleY(1);
}
.item-list-leave-active {
position: absolute;
}
.item-list-leave-to {
opacity : 0;
transform : scaleY(0);
transform-origin: center top;
}
I wish I could've found a more "Vue-y" way of handling this, however I ended up going this route. Essentially I added a class to the body and removed all transitions. Then on the created lifecycle of my component, I remove that class. This removes the transition on page load, but still keeps the transition on click of the button like I want.
You can dynamically change the name value of the transition-group. Maybe on page load have a value different from the value that has the correct class name that the CSS targets. Then in the mounted lifecycle hook you can change it back to the correct class name.
You need to bind the duration for transition-group
template:
<transition-group
:duration="duration"
name="item-list"
tag="div">
<item-row
v-for="item in items"
:key="item.id"
:item="item" />
</transition-group>
script:
data() {
return {
duration: 0,
items: [
{id: 1},
{id: 2}
]
}
},
methods: {
add() {
if(this.duration===0) this.duration = 250
this.items.push({id: 'xxx'})
}
}
In case anyone comes across this like I did.
I ended up achieving this by having a transitionsOn flag added to the data (didn't seem to matter what it was initialised to), and a computed name for the transition, i.e.
<transition-group :name="transitionName">
in computed, I then had, for a transition called 'flash'
computed: {
transitionName() {
return this.transitionsOn ? 'flash' : 'disabled';
},
},
I would then set this.transitionsOn = true when I wanted it to fire.
Took a lot of fiddling about to figure this out but it seems to work OK

vuetify: calculate grid width by passed props

I want to make a menu component that builds same-sized buttons based on the amount of menuItems passed in as props.
similar to
https://stackoverflow.com/a/47215040/6066886
i want to give the v-flex a conditional attribute. (xs6 for two items, xs4 for three and so on)
(something like <v-flex v-for="item in menuItems" xs[12 / menuItems.length]>)
in the linked question, the idea is to pass "xs10" or not, based on a condition.
i want to calculate WHICH of those will be added to my v-flex, but i have no idea how that would be done.. as i can't v-bind anything... can anyone help me?
You can bind a computed property as class object:
<v-flex :class="xsComputed" v-for="(item,i) in items" :key="i">{{item}}</v-flex>
...
new Vue({
el: '#app',
data: function() {
return {
items: [1, 2, 3, 4]
}
},
computed: {
xsComputed: function() {
var step = Math.floor(10 / this.items.length)
var xsc = {}
xsc['xs' + step] = true
console.log(xsc)
return xsc
}
}
})
https://jsfiddle.net/26zfLn8j/
Ok, I see your problem now. I was digging around a little and it's not easy to solve, cause the v-flex doesn't support params, it should be declared as a attribute and not class (as says this response https://stackoverflow.com/a/47215040/6058255).
As there as no way to create a attribute without value, like I said in the comment, and affter some tests, I will do as follow:
<v-flex v-bind:class="'xs'+12/menuItems.length" v-for="menuItem in menuItems">
{{menuItem}}
</v-flex>
This should render the v-flex element with a class like: "xs12","xs6","xs4"..
The then you should only copy the class style for this elements that have the v-flex for it, something like:
.xs12{ max-width:100%; }
.xs6{ max-width: 50%; }
.xs4{ max-width: 25%; }
.xs3{ max-width: 33.333333333%; }
...
Maybe is not the more elegant solution but it's easy and it works for you I think.
Hope it helps!
EDIT:
Reviewing stdob-- answer I now see that only with the expression:
<v-flex v-bind:class="'xs'+12/menuItems.length" v-for="menuItem in menuItems">
{{menuItem}}
</v-flex>
Should work. The flex component will render as flex xs12 (for instance).