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).
Related
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!
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
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
When we try to fill forms in the internet, required fields are marked using a red color ' * ' mark to indicate that the field is a must.
Like that is there a way to indicate users to required fields in vuetify.js?
It's a bit of a pain, but there is a 'label' named slot and you can do something like this:
<v-text-field
v-model="loginInfo.email"
autofocus
name="email"
type="email">
<template #label>
<span class="red--text"><strong>* </strong></span>Email
</template>
</v-text-field>
From v1.1.0 docs:
The required prop no longer explicitly adds an asterisk to the label. All of its functionality to validation was removed for v1.0.
So apparently nothing will set it as required anymore, we have to add it manually in the label:
label="Name*"
Or you could use CSS:
.required label::after {
content: "*";
}
Tho you must add required class manually (name of the class is arbitrary of course).
You are able to pass a rules prop to a v-text-field.
E.g,
<v-text-field
v-model="title"
:rules="['Required']"
label="Title"
counter
maxlength="20"
></v-text-field>
See this Vuetify example for a fuller picture: https://github.com/vuetifyjs/vuetifyjs.com/blob/master/src/examples/text-fields/validation.vue
required is also an HTML property. You could just add it to the HTML Element like this:
<v-text-field
v-model="title"
label="Title"
counter
maxlength="20"
required
></v-text-field>
I have the solution, with add this css class into main css file or in main.js.
div[aria-required=true].v-input .v-label::after {
content: " *";
color: red;
}
That's it, in this add field required:
<v-text-field required>
Performance wise, I don't know if this is the best solution. But it works.
Import the JavaScript file bellow into you application bootstrap (or something like that).
import Vue from 'vue';
Vue.mixin({
mounted() {
const e = this.$el;
if ('querySelector' in this.$el) {
const i = this.$el.querySelector('input[required]');
if (i !== null) {
const l = i.previousSibling;
if (l.querySelector('.required.sign') === null) {
const r = document.createElement('span');
// l.classList.add('required');
r.classList.add('required', 'sign');
r.appendChild(document.createTextNode('*'));
l.appendChild(r);
}
}
}
},
});
Nuxt.js: put the file above into the plugins folder. Include its path on the plugins array on the nuxt.config.js file.
Add the rule bellow to your global CSS / theme.
.v-label > .required.sign {
color: darkred;
font-weight: bold;
margin-left: .25em;
}
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()
}