show form as dropdown to button (vuetify) - javascript

I have a v-btn.
When clicked on it, I want to have a dropdown to it. I don't want the dropdown to be a list, but the form with 3 labels and 3 text fields. Each label for each textfield.
Problem 1) When showing labels and textfields, they are all at the same line(horizontally). how do I make label and textfield below it?
Problem 2) WHen that dropdown appears and I put mouse on textfield, dropdown completely closes. I only want to close it when i click the button which also resides on that dropdown at the end of the form. how do I not close it when clicked on it ?
P.S. I am using v-menu for dropdown.

Problem 1
Can you please provide a small example of your code?
In Vuetify you can just use a v-text-field and give it a label via the label prop.
Problem 2
You can set close-on-click and close-on-content-click to false to prevent the dropdown from closing.
Small example:
new Vue({
el: "#app",
vuetify: new Vuetify(),
data() {
return {
menuOpen: false,
firstname: "",
lastname: ""
};
},
methods: {
save() {
alert(`Your name is ${this.firstname} ${this.lastname}!`);
this.menuOpen = false;
}
}
});
#app { height: 400px; }
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#latest/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-content>
<v-menu offset-y :close-on-click="false" :close-on-content-click="false" v-model="menuOpen">
<template v-slot:activator="{ on }">
<v-btn v-on="on" class="ma-4">BUTTON</v-btn>
</template>
<v-card>
<v-card-text>
<v-text-field label="First Name" v-model="firstname"></v-text-field>
<v-text-field label="Last Name" v-model="lastname"></v-text-field>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="grey darken-2" #click="menuOpen = false" dark>CANCEL</v-btn>
<v-btn color="primary" #click="save">OK</v-btn>
</v-card-actions>
</v-card>
</v-menu>
</v-content>
</v-app>
</div>

1) Vuetify text fields have a prop named "label" - if you bind the label text to this prop it'll automatically appear above the text field. Otherwise, if you for some reason want to create your own label, just wrap both the label and input in a v-layout OR wrap the label and input in the same element (e.g. div) and make sure the label is a div
<v-flex xs12 sm6>
<div>test label</div>
<v-text-field
v-model="title"
:rules="rules"
counter="25"
label="Outline"
outline
></v-text-field>
</v-flex>
2) the menu has a "close-on-content-click" prop that defaults to true, which you can set to false. This will prevent the menu from closing on click

Related

How to apply a hover function to a Vue / Vuetify Autocomplete autocomplete list?

I am more of a Vue-Noob, and find it to be a bit complicated to understand. Maybe you fellas see that code, and have the "best practice" or most compact solution for my problem:
I have an autocomplete dropdown box. On expand, i see a list with clickable entries. I would need to get the information of the hovered item, if the mouse hovers over the list.
Like, the method "doFunnyStuff" would push the data of the hovered object on hovering to a method, and do something with it (maybe externally or so)
Thank you in advance for any helpful comment!
<template>
<v-autocomplete
v-model="selected"
dense
outlined
hide-details
return-object
background-color="white"
light
:placeholder="placeholder"
hide-no-data
style="width: 500px"
:loading="loading"
:search-input.sync="query"
:items="items"
clearable
>
<template slot="selection" slot-scope="{ item }" return-object>
<v-list-item #mouseenter="doFunnyStuff(item)">
<v-list-item-content>
<v-list-item-title> {{ item.text }}} </v-list-item-title>
</v-list-item-content>
</v-list-item>
</template></v-autocomplete
>
</template>
</template>
Maybe I misunderstood your question, but when you want to do something with hovered item of expanded list, you should use item slot instead of selection.
Selection slot is used just for your selected item on top of the component, so your code works, but only when you hover your already selected item.
Mouseenter event is not related for any component in vuetify, it's an JS event that may be appended to any component (if was not appended before by vuetify or any different library, ofc).
So your code may be like:
<div id="app">
<v-app id="inspire">
<v-autocomplete
v-model="value"
:items="items"
dense
filled
label="Filled"
>
<template #item="{ item, on, attrs }">
<v-list-item #mouseenter="doFunnyStuff(item)" v-on="on" v-bind="attrs">
<v-list-item-content>
<v-list-item-title> {{ item }} </v-list-item-title>
</v-list-item-content>
</v-list-item>
</template>
</v-autocomplete>
<div>
<p>{{ hoveredItem }}</p>
</div>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
items: ['foo', 'bar', 'fizz', 'buzz'],
value: null,
hoveredItem: "not hovered yet"
}),
methods: {
doFunnyStuff (item) {
this.hoveredItem = item;
}
}
})
Codepen link with an example

How to modify a child component's colour attribute from the parent in vue js

I have a child Card component:
<template>
<v-card
class="mx-auto"
max-width="500"
color=color
outlined
dark
>
<v-list-item three-line>
<v-list-item-content>
<div class="overline mb-4">
OVERLINE
{{color}}
</div>
<v-list-item-title class="headline mb-1">
Headline 5
</v-list-item-title>
<v-list-item-subtitle>Greyhound divisely hello coldly fonwderfully</v-list-item-subtitle>
</v-list-item-content>
<v-list-item-avatar
tile
size="80"
color="grey"
></v-list-item-avatar>
</v-list-item>
<v-card-actions>
<v-btn
outlined
rounded
text
>
Button
</v-btn>
</v-card-actions>
</v-card>
</template>
<script>
export default {
name: 'Card',
props: {
color: String
}
}
</script>
And from the parent component I want to pass in the color to the child. A part of the parent component's code is shown below.
<template>
<Card v-bind:color="color"/>
</template>
<script>
export default {
data() {
return {
color: "#FFC400"
}
},
}
</script>
As you can see I tried to use a prop to pass the color from the parent to the child, however even though I'm able to pass the data to the child, {{color}} prints out #FFC400 I'm not sure how to assign the color value to the v-card's color attribute. How can I achieve this? Thank you.
The only thing missing is to also bind the prop to the color attribute of the <v-card>, otherwise it's only receiving the string "color", rather than the variable of that name.
You can use v-bind:color="color" or the shorthand :color="color"
<v-card
class="mx-auto"
max-width="500"
:color="color"
outlined
dark
>

Vue.js: How can I put a Login Modal inside a dropdown Menu?

I have the following dropdown menu:
<template>
<v-menu close-on-click transition="slide-y-transition">
<template v-slot:activator="{ on, attrs }">
<v-btn color="primary" v-bind="attrs" v-on="on">
Menu
</v-btn>
</template>
<v-list>
<v-list-item v-for="(item, index) in menuItemsMisc" :key="index" v-model="item.model">
<v-list-item-title>
<v-btn block color="white" #click="item.fn">{{ item.title }}</v-btn>
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
<!-- Modal code here -->
</template>
<script>
export default {
name: 'MenuBar',
data: () => ({
loginModal: false,
purchaseModal: false,
menuItemsMisc: [
{ title: 'Login',
model: 'loginModal',
fn: () => { this.loginModal = true}
},
{ title: 'Purchase',
model: 'purchaseModal',
fn: () => { this.purchaseModal = true }
},
]
}),
}
</script>
And I am trying to display this Login Modal When the Login Button is clicked in the dropdown.
<v-dialog v-model="loginModal" persistent max-width="500px">
<v-card class="elevation-12">
<v-toolbar color="primary" dark flat>
<v-toolbar-title>Login form</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card-text>
<v-form>
<v-text-field name="login" prepend-icon="mdi-account" type="text"></v-text-field>
<v-text-field id="password" name="password" prepend-icon="mdi-lock" type="password">
</v-text-field>
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary">Login</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
But whenever I click the Login or Purchase Button, I have an error that says:
TypeError: Cannot set property 'loginModal' of undefined
What is the Problem here?
From the Vue docs on v-model:
You can use the v-model directive to create two-way data bindings on form input, textarea, and select elements. It automatically picks the correct way to update the element based on the input type.
The v-model property on your <v-dialog> component is expecting it to be an input of some type.
You should be able to simply change this to a v-if:
<v-dialog v-if="loginModal" persistent max-width="500px">
This will cause the <v-dialog> component to display when your button is clicked.
EDIT: Please also make sure your data property on the Vue instance is declared as a class-style function. If you use a lambda function you will lose the this scope when referring to this.loginModal:
export default {
...
data() {
return {
...
}
}
}

How to have the button span the whole width?

I am using Vuetify card with a layout and rendering some dynamic vuetify components inside of the card on checkbox selection which renders either a divider, a spacer, toolbar or button but i am not able to figure out how can i make the buttons span the entire width?
Basically the dynamic button should look like the button at the end rendering the entire width.
Please check this codepen.
Please check this working example:-
new Vue({
el: "#app",
data() {
return {
pricing: [{
text: "Actual price:",
value: "$17,000",
},
{
text: " Discount",
value: "$12,345",
}
],
elements: [{
title: "Divider",
value: "v-divider"
},
{
title: "Toolbar",
value: "v-toolbar"
},
{
title: "Button",
value: "v-btn"
}
],
selected: []
};
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<link rel="stylesheet" href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons'>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet" />
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout row>
<v-flex xs6>
<v-card>
<v-card-text>
<v-layout row justify-space-between v-for="option in pricing" :key="option.value" class="my-3">
<span :class="option.class">{{option.text}}</span>
<component v-for="(el, i) in selected" :key="i" :is="el.value"></component>
<span>{{option.value}}</span>
</v-layout>
<v-layout row justify-center>
<v-flex xs11>
<v-btn block>
Request
</v-btn>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
<v-flex v-for="el in elements" :key="el.value">
<v-checkbox :value="el" v-model="selected" :label="el.title">
</v-checkbox>
</v-flex>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
Any help will be appreciated. Thank you so much.
Use .flex.xs12 (12 = flex-basis: 100%;)
-or-
remove xs12 (And add button block attribute = flex: 1 0 auto;).
<!-- block buttons extend the full available width -->
<template>
<v-btn block>
Block Button
</v-btn>
</template>
https://vuetifyjs.com/en/components/buttons/#block

Unable to insert New Line in a string of the vuetify dialog

I attempted to insert a new line in the string which is the Vuetify dialog text by using \n in the string. But it does not work.
Here is the code for the function that calls Vuetify dialog
handleDialog()
{
this.dialogHeading = "Clearing all component data"
this.dialogText = "Do you really want to clear all the component data?\nThis will clear the components except the pressure and composition basis!"
this.dialogBtn1 = "Cancel"
this.dialogBtn2 = "Yes"
this.isDialog = true
}
And here is the code for displaying the Vuetify dialog
<v-layout row wrap >
<v-flex class="text-xs-center">
<v-dialog v-model="isDialog" persistent max-width=400>
<v-card>
<v-card-title class=" error title white--text
darken-2 font-weight-bold">{{dialogHeading}}
</v-card- title>
<v-card-text>{{dialogText}}</v-card-text>
<v-card-text v-if="dialogText2">{{dialogText2}}
</v-card-text>
<v-card-actions >
<v-btn v-if="dialogBtn1" flat class=
"align-content-center d-flex mx-auto" dark
color="red darken-1 font-weight-bold"
text
#click="clearDialog('no')">{{dialogBtn1}}</v-btn>
<v-btn v-if="dialogBtn2" flat
class="align-content-center d-flex mx-auto
font-weight-bold" dark color="green darken-1"
text #click="clearDialog('yes')">{{dialogBtn2}}
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-flex>
</v-layout>
I've tried using '\n' .
I need the second sentence in the next line
Here is the screenshot of the result that I get
Any help would be appreciated. Thank you in advance
You should use <br/> tag instead of \n in order to go to the next line and use v-html directive to render that string :
this.dialogText = "Do you really want to clear all the component data?<br/>This will clear the components except the pressure and composition basis!"
template:
<v-card-text v-html="dialogText"></v-card-text>
One way to achieve this would be to wrap each line in a block-level element such as a <div> within the template. The original string could be split on newlines and iterated accordingly:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
dialogText: 'First line\nSecond line'
}
}
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://unpkg.com/#mdi/font#3.9.97/css/materialdesignicons.css" rel="stylesheet">
<link href="https://unpkg.com/vuetify#2.0.17/dist/vuetify.css" rel="stylesheet">
<script src="https://unpkg.com/vue#2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify#2.0.17/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-card>
<v-card-title>Title</v-card-title>
<v-card-text>
<div v-for="(text, index) in dialogText.split('\n')" :key="index">
{{ text }}
</div>
</v-card-text>
</v-card>
</v-app>
</div>
This retains the default escaping behaviour that would be lost using v-html.
The easiest way is to use div, like this:
<v-card-text>
<div>{{ dialogText }}</div>
<div>Whitsunday Island, Whitsunday Islands</div>
</v-card-text>
The code is from vuetify card docs
you can put text-pre-wrap on your element's class and just use regular \n breaks or even template strings with line breaks in them:
<v-card-text class="text-pre-wrap">
{{dialogText}}
</v-card-text>
<!-- The same as -->
<v-card-text class="text-pre-wrap">
{{
`Do you really want to clear all the component data?\nThis will clear the components except the pressure and composition basis!`
}}
</v-card-text>
<!-- The same as -->
<v-card-text class="text-pre-wrap">
{{
`Do you really want to clear all the component data?
This will clear the components except the pressure and composition basis!`
}}
</v-card-text>

Categories

Resources