Vuetify how to mark field as required - vuejs2

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;
}

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

Vue.js How to define (override) css style in a Component?

The default style for the p tag on my page has some bottom margin. My component uses p tags, and accordingly, the p tags in my component text show the corresponding bottom margin. How can I override/define new css style for the p tags in my component. I define my component like this:
Vue.component ('activity-component', {
props: {
customer_id:{},
is_admin:{},
isAdmin:{},
isKitsActionplan:{},
....
template:
`<div
class="row msDashboard-box"
style="cursor:default;padding-top:12px;
padding-bottom:12px;"
>
...
<p> ... </p>
});
Maybe u can try this approach,
Pass a variable with the class name to the component
<my-component v-bind:class="variable with class name"></my-component>
Then apply a rule to all p elements inside it, something like this i guess:
.test p{
your styles
}
U can see more here: vue api class and style bindings
I dont know for sure if this was what you wanted, but i gave it a shot :)
You have several options - choose your own adventure:
Use a global utility style
Somewhere globally, define a utility class like:
.u-margin-reset {
margin: 0;
}
Then in your template:
<p class="u-margin-reset">hello</p>
Use scoped CSS
If you are using single file components, you can use scoped css:
<template>
<p class="special-p">hello</p>
</template>
<style scoped>
.special-p {
margin: 0;
}
</style>
Use inline styles
Vue.component('activity-component', {
template: `<p style="margin:0;"></p>`,
});
or
Vue.component('activity-component', {
computed: {
myStyle() {
return {
margin: 0,
};
},
},
template: `<p :style="myStyle"></p>`,
});
As an aside, I'd recommend using a CSS reset that globally resets the margins of all elements to 0. Then each component should set the margins as needed for its child elements/components. This may not be reasonable if you already have a large codebase, however.

Changing the Vuetify carousel height

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()
}

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).