Show mutiple v-dialog boxes with different content in vue.js - javascript

Hii I am working on the Vue.js template and I stuck at a point where I need to show dynamic v-dialog using looping statement but now it shows all.
Dom:
<template v-for="item of faq">
<div :key="item.category">
<h4>{{ item.heading }}</h4>
<div v-for="subitems of item.content" :key="subitems.qus">
<v-dialog
v-model="dialog"
width="500"
>
<template v-slot:activator="{on}">
{{subitems.qus}}
</template>
<v-card>
<v-card-title
class="headline grey lighten-2"
primary-title
>
Privacy Policy
</v-card-title>
<v-card-text>
{{ subitems.ans }}
</v-card-text>
<v-divider></v-divider>
</v-card>
</v-dialog>
</div>
</div>
</template>
Script:
export default {
data: () => ({
faq,
dialog:false,
}),
}
I do not understand how I can do this. If I click on one button then it shows all.

There must a design a pattern for this one but a quick solution would be to create array of booleans for v-models of dialogs. something like below
export default {
data: () => ({
faq,
dialog: [] // Array instead of Boolean.
}),
}
and
<template v-for="item of faq">
<div :key="item.category">
<h4>{{ item.heading }}</h4>
<div v-for="(subitems, index) of item.content" :key="subitems.qus">
<v-dialog
v-model="dialog[index]"
width="500"
>
<template v-slot:activator="{on}">
{{subitems.qus}}
</template>
<v-card>
<v-card-title
class="headline grey lighten-2"
primary-title
>
Privacy Policy
</v-card-title>
<v-card-text>
{{ subitems.ans }}
</v-card-text>
<v-divider></v-divider>
</v-card>
</v-dialog>
</div>
</div>
</template>

Brother, you are doing a very small mistake, you should not keep your v-dialog component inside your loop, take this out from loop block and don't take dialog as empty array keep it false.

Related

v-card is not being shown completly

I am working with vuetify and I want to implement a Stepper.
Within the stepper I want to have v-card which once clicked on read more would open. So far the functions are working.
The problem is that when I only open a card - meaning in the index.vue I put the card component instead of the stepper, the card opens reacts perfectly. But, when the card is within the stepper component, when I press on read more it is only shown a part of it. I guess some element is having a fixed size and wont resize, but I cannot figure it out where exactly the problem is. Any help is welcomed!
My index.vue file looks like this:
<template>
<v-container>
<v-app>
<div>
<Stepper/>
</div>
</v-app>
</v-container>
</template>
<script>
import Stepper from "../components/Stepper.vue";
export default {
data: () => ({
}),
components: {Stepper }
}
</script>
The Stepper.vue component looks like this:
<template>
<v-stepper v-model="e6" vertical ref="stepper">
<!--- Step 1-->
<v-stepper-step :complete="e6 > 1" step="1">
</v-stepper-step>
<v-stepper-content step="1">
<Card1 />
</v-stepper-content>
<!--- Step 2-->
<v-stepper-step :complete="e6 > 2" step="2">
</v-stepper-step>
<v-stepper-content step="2">
<Card2 />
</v-stepper-content>
<!--- Step 3-->
<v-stepper-step :complete="e6 > 3" step="3">
</v-stepper-step>
<v-stepper-content step="3">
<Card2 />
</v-stepper-content>
</v-stepper>
</template>
The cards inside are from format identical only the text is different. Hence I will post only one card:
<template>
<v-hover >
<template v-slot:default="{ hover }">
<v-card class="mx-auto">
<v-img class="white--text" src="picture1.png" width="300" height="169">
<v-card-title class="text-h5">
{{ $t('welcome_hello') }}
</v-card-title>
</v-img>
<v-card-actions>
<v-btn text color="teal accent-4" #click="openCard()">
Learn More
</v-btn>
</v-card-actions>
<v-expand-transition>
<v-card v-if="reveal" class="transition-fast-in-fast-out v-card--reveal" style="height: 100%;">
<v-card-text class="pb-0">
<p class="text-h4 text--primary">
{{ $t('welcome_message1') }}
</p>
<p>{{ $t('welcome_message2') }}</p>
<p>{{ $t('welcome_message3') }}</p>
</v-card-text>
<v-card-actions class="pt-0">
<v-btn text color="teal accent-4" #click="nextStep()">
Next
</v-btn>
</v-card-actions>
</v-card>
</v-expand-transition>
</v-card>
</template>
</v-hover>
</template>
<script>
export default {
data: () => ({
reveal: false,
}),
methods: {
openCard() {
this.reveal = true
},
closeCard() {
this.reveal = false
},
completedCard(){
},
nextStep() {
this.closeCard()
this.$root.$emit('nextStepFunction') //like this
},
}
}
</script>
<style>
.v-card--reveal {
bottom: 0;
opacity: 1 !important;
position: absolute;
width: 100%;
}
</style>
You should give your v-card a height and then overflow to scroll.
<v-card height="450" style="overflow-y: scroll; overflow-x: hidden">
// Your card body
</v-card>

Vuetify : Tooltip doesn't work with custom Component

My tooltip doesn't work with my Custom Component. I wrap a Dialog in a Component and I want to add a tooltip.
My Vue.js version is 2.5.17 and Vuetify 2.1.15
Componant A :
<v-tooltip bottom>
<template v-slot:activator="{ on }" v-slot:item={item}>
<ComponentB v-on="on">
</ComponentB>
</template>
<span>Hello world!</span>
</v-tooltip>
Component B:
<template>
<v-dialog v-model="dialog" persistent max-width="800px">
<template v-slot:activator="{ on }">
<v-icon small v-on="on">
add_comment
</v-icon>
</template>
<v-card>
<v-card-title>
<span class="headline">Title</span>
<v-spacer></v-spacer>
<v-btn icon #click="dialog = false">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<v-card-text class="pb-0">
Hello world!
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="primary"
text
#click="dialog = false"
>
I accept
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
I am beginner in VueJs, so may someone can help me :)
I would personally just move the tooltip into the child component, since it is technically part of the child component anyway. I did the best I could with the example code below, given the limited amount of code you provided in your question. Hopefully this helps!
<!-- Component A (Parent) -->
<template>
<ComponentB :item="item" />
</template>
<!-- Component B (Child) -->
<template>
<v-dialog v-model="dialog" persistent max-width="800px">
<v-tooltip bottom>
<template v-slot:activator="{ on }" v-slot:item="item">
<v-icon small v-on="on">
add_comment
</v-icon>
</template>
<span>Hello world!</span>
</v-tooltip>
<v-card>
<v-card-title>
<span class="headline">Title</span>
<v-spacer></v-spacer>
<v-btn icon #click="dialog = false">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<v-card-text class="pb-0">
Hello world!
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="primary"
text
#click="dialog = false"
>
I accept
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
props: {
item: {
type: Object,
default() {
return {};
}
}
}
};
</script>

How to avoid #click on only one child component

For example if I click on all the v-card I am redirecting to an other link BUT if I click on the title World of the Day and only on the title I don't want to do nothing. How to avoid to be redirected when clicking on title ?
template>
<v-card
class="mx-auto"
max-width="344"
#click="goToAnOtherLink"
>
<v-card-text>
<div>Word of the Day</div>
<p class="display-1 text--primary">
be•nev•o•lent
</p>
<p>adjective</p>
<div class="text--primary">
well meaning and kindly.<br>
"a benevolent smile"
</div>
</v-card-text>
<v-card-actions>
<v-btn
text
color="deep-purple accent-4"
>
Learn More
</v-btn>
</v-card-actions>
</v-card>
</template>
If it's only the title, use the stop event modifier. This is easier than having the logic in the method.
<v-app>
<v-card class="mx-auto" max-width="344" #click="goToAnOtherLink">
<v-card-text>
<div class="title" #click.stop>Word of the Day</div>
<p class="display-1 text--primary"> be•nev•o•lent </p>
<p>adjective</p>
<div class="text--primary"> well meaning and kindly.<br> "a benevolent smile" </div>
</v-card-text>
<v-card-actions>
<v-btn text color="deep-purple accent-4"> Learn More </v-btn>
</v-card-actions>
</v-card>
</v-app>
https://codeply.com/p/2ExpE6PF6F
Add a class to the title div as well, and check the classes of your event's target inside the function goToAnOtherLink. Then you can use stopPropagation() along with the custom code you have in that function.
new Vue({
el: "#app",
data() {},
methods: {
goToAnOtherLink(e) {
if (e.target.classList.contains("title") || e.target.classList.contains("display-1")) {
e.stopPropagation()
console.log("Cancelled Navigation!")
} else {
console.log("Navigated!")
}
}
}
});
<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 href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" />
<div id="app">
<v-app>
<v-card class="mx-auto" max-width="344" #click="goToAnOtherLink">
<v-card-text>
<div class="title">Word of the Day</div>
<p class="display-1 text--primary">
be•nev•o•lent
</p>
<p>adjective</p>
<div class="text--primary">
well meaning and kindly.<br> "a benevolent smile"
</div>
</v-card-text>
<v-card-actions>
<v-btn text color="deep-purple accent-4">
Learn More
</v-btn>
</v-card-actions>
</v-card>
</v-app>
</div>
You can wrap your v-card in a div and use absolute positioning to place the title; so that the title is in "front" of the v-card thus clicking on it does nothing.
Pseudo-code
<div>
<span>Word of the day</span> <!-- use absolute to position inside the div -->
<v-card></v-card>
</div>

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>

How to remove vuetify card on clicking a button

I have added a vuetify card and a button on it. I want that when the button is clicked, the card disappears. How can I do that?
Below is how my component looks like. I want to add a method to do so but don't know what the method will be.
<template>
<div class="notifications">
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-card flat color="green">
<v-card-title primary-title>
<div>
<h3 class="headline">Neu Benutzer angelegt</h3>
<div> {{ card_text }} </div>
</div>
</v-card-title>
<v-card-actions>
<div class="close"><v-btn #click="removeMessage(2)">Ok</v-btn></div>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</div>
</template>
<script>
export default {
data () {
return {
card_text: 'Success!'
}
},
methods: {
removeMessage(seconds) {
},
},
};
</script>
You can hide it with v-if and a boolean flag:
<template>
<div class="notifications" v-if="show">
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-card flat color="green">
<v-card-title primary-title>
<div>
<h3 class="headline">Neu Benutzer angelegt</h3>
<div> {{ card_text }} </div>
</div>
</v-card-title>
<v-card-actions>
<div class="close"><v-btn #click="removeMessage(2)">Ok</v-btn></div>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</div>
</template>
<script>
export default {
data () {
return {
card_text: 'Success!',
show:true;
}
},
methods: {
removeMessage(seconds) {
setTimeout(()=> this.show = false, seconds * 1000);
},
},
};
</script>
You can also use v-show and make something like this: CodePen

Categories

Resources