Currently ,my snackbar is not showing after clicking the button. I want to pass the snackbar component function to my button which located in Add.vue. Is there any way to pass the component function?
Snackbar.vue in component folder
<template>
<div class="text-center ma-2">
<v-snackbar v-model="snackbar" :timeout="timeout" top color="primary">
{{ text }}
<template v-slot:action="{ attrs }">
<v-btn color="pink" text v-bind="attrs" #click="snackbar = false" >
Close
</v-btn>
</template>
</v-snackbar>
</div>
</template>
<script>
export default {
data: () => ({
snackbar: false,
text: 'My timeout is set to 2000.',
timeout: 2000,
})
}
</script>
Add.vue file
<template class="id">
<base-form title="Add Medical Activities">
<template v-slot:actions>
<SnackBar :snackbar="true"/>
<v-btn
dark
#click="snackbar = true"
>test</v-btn>
</template>
<form-input v-model="inputs" :select-multiple="false"></form-input>
</base-form>
</template>
<script>
import SnackBar from '~/components/SnackBar.vue'
export default {
components: { BaseForm, FormInput, SnackBar },
you only need boolean passed on your v-model
<v-snackbar v-model="snackbar">
hai
</v-snackbar>
<v-btn #click='snackbar = true'>
any operation that make change snackbar to true, snackbar will open it like what you expected
Try this out:
Add.v
<template>
<div>
<Snackbar :key="snakKey" v-if="showSnackbar" #toggleSnackbar="showSnackbar = false" />
<v-btn color="primary" #click="snackbarHandler">
Show Snackbar
</v-btn>
</div>
</template>
<script>
export default {
name: "Add",
data: () => ({
showSnackbar: false,
snakKey: 0,
}),
methods:{
snackbarHandler(){
this.snakKey++;
this.showSnackbar = true;
}
}
}
</script>
Snackbar.vue
<template>
<div class="text-center ma-2">
<v-snackbar v-model="snackbar" :timeout="timeout" top color="primary">
{{ text }}
<template v-slot:action="{ attrs }">
<v-btn color="pink" text v-bind="attrs" #click="$emit('toggleSnackbar')" >
Close
</v-btn>
</template>
</v-snackbar>
</div>
</template>
<script>
export default {
data: () => ({
snackbar: true,
text: 'My timeout is set to 2000.',
timeout: 3000,
})
}
</script>
I hope this helps you.
Related
I have a prop and currently am able to get the data of the prop, Am trying a way to capture the item of the prop when saving the form.
Is there a way where i can take the value and pass if in a hidden text-area and bind the data to the vmodel?
Any help I appreciate.
<v-dialog v-model="dialog" persistent max-width="800">
<template v-slot:activator="{ on }">
<v-btn dark v-on="on" color="primary" round> Make payment </v-btn>
</template>
<v-card>
<v-card-title class="headline primary">
<span class="white--text">Add a new Doctor Payment Record {{ queueId }}</span>
<v-btn icon dark #click.native="dialog = false" absolute right>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<v-card-text>
<users-search
:leave-selected="true"
idOnly
label="Select Doctor"
#results="setDoctor"
>
</users-search>
<div class="row px-3">
<v-autocomplete
class="px-3 col-sm-8"
v-model="expense.bank"
v-if="banks.data"
:items="banks.data"
outline
chips
label="Select bank"
item-text="name"
item-value="id"
>
</v-autocomplete>
<v-text-field
class="px-3 col-sm-8"
outline
flat
v-model="expense.amount"
type="number"
#input="expense.percentage()"
required
label="Amount *"
persistent-hint
/>
</div>
<v-text-field
class="px-3"
outline
flat
v-model="expense.total_paid"
required
label="amount paid"
persistent-hint
/>
<v-text-field
class="px-3"
outline
flat
:value="setQueue"
v-model="expense.queueId"
required
:label=queueId
persistent-hint
/>
<v-alert :value="true" type="error" v-if="errors.any()">
<div v-html="errors.display()"></div>
</v-alert>
<v-layout row wrap>
<v-flex xs12>
<v-btn
color="success"
:loading="saveLoader"
#click="recordExpense()"
>save</v-btn
>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
</v-dialog>
</template>
<script>
import NewUser from "#finance/libs/users/NewUser";
import {mapActions, mapGetters} from "vuex";
export default {
props: [
'queueId'
],
data: () => ({
dialog: false,
expense: new NewUser(),
saveLoader: false,
}),
computed: {
...mapGetters({
banks: "getBanks",
}),
balance: function () {
return parseFloat(10);
},
submitted() {
return this.expense.form.submitted;
},
contaminated() {
return this.expense.form.errorDetected;
},
errors() {
return this.expense.form.errors;
},
},
watch: {
submitted(v) {
if (v) {
this.saveLoader = false;
}
},
contaminated() {
this.saveLoader = false;
},
},
methods: {
...mapActions({
fetchBanks: "setBanks",
}),
setDoctor(user) {
this.expense.doctor_id = user.id;
},
setQueue(){
console.log(this.queueId);
this.expense.queueId = this.queueId;
},
async recordExpense() {
this.saveLoader = true;
let response = await this.expense.saveExpense();
this.saveLoader = false;
if (response) {
this.dialog = false;
this.$emit("expenseCreated");
}
},
},
mounted() {
this.fetchBanks();
}
};
</script>
The prop queueId i also want to store it along with the user information from the form.
Try this one, it should work:
<template>
<textarea v-model="hiddenValue" :style="{ display: 'none' }"></textarea>
</template>
<script>
export default {
props: [ 'queueId' ],
data() {
return {
hiddenValue: this.queueId
}
}
}
</script>
In case you will no need the prop to be modified, please bind the texarea value to the prop directly:
<textarea hidden v-model="queueId" :style="{ display: 'none' }></textarea>
everyone, I am new to vuejs and vuetify and trying to make a book app but the problem is all the code is complete but when I click on the dropdown item it shows all the books item but I want to show only selected book item.
This is my HTML where I am stuck I am doing mistakes here this and I am failed many times cannot get my answer
<v-container fluid>
<v-row aign="center">
<v-col cols="12">
<v-toolbar-title>State Selection</v-toolbar-title>
<div v-on-clickaway="away" class="searchField dropdown">
<v-text-field
:label="labeling"
v-model="search"
#input="waitForSearch"
>
</v-text-field>
<!-- <div class="bookParent" v-for="item in items" :key="item.id"> -->
<!-- <img :src="item.volumeInfo.imageLinks.thumbnail" /> -->
<div
class="clickUpdateElement"
v-for="(item, index) in items"
:key="item.id"
>
<HelloWorld v-show="show">
<template v-slot:contentHandler class="option" id="option1">
<div
#click="clickCard(item, $event.target)"
class="containerForI"
>
<v-img>
<img :src="item.volumeInfo.imageLinks.thumbnail" />
</v-img>
<a class="anchorTag">{{ item.volumeInfo.title }}</a>
<!-- <span>{{ item.volumeInfo.author }}</span> -->
</div>
</template>
</HelloWorld>
<div class="content">
<Content v-show="show2" #load="updateCard(item, $event.target)">
<template v-slot:cardContent>
<v-card class="mx-auto" elevation="2" outlined shaped>
<v-list-item three-line>
<v-list-item-avatar>
<!-- <v-img :src="imageSrc"></v-img> -->
</v-list-item-avatar>
<v-list-item-content>
<v-card-title>
{{ item.volumeInfo.title }}
</v-card-title>
<v-card-subtitle>
{{ index }} {{ item.volumeInfo.description }}
</v-card-subtitle>
</v-list-item-content>
<v-card-actions>
<v-btn primary>Act</v-btn>
</v-card-actions>
</v-list-item>
</v-card>
</template>
</Content>
</div>
</div>
<v-btn #click="show2 = false">Remove</v-btn>
</div>
</v-col>
</v-row>
</v-container>
MY JS
import axios from "axios";
import { directive as onClickaway } from "vue-clickaway";
import HelloWorld from "../components/HelloWorld";
import Content from "../components/Content";
export default {
name: "Home",
directives: {
onClickaway: onClickaway,
},
data() {
return {
BASE_URL: "https://www.googleapis.com/books/v1/volumes",
items: [],
search: "",
timerId: "",
labeling: "Search For Book",
show: false,
show2: false,
imageSrc: "",
showTitle: "",
showDescription: "",
};
},
components: {
HelloWorld,
Content,
},
created() {},
computed: {},
//Fetch the required Information from Google Book Api
watch: {},
methods: {
async getBooks() {
this.show = true;
let response = await axios.get(`${this.BASE_URL}`, {
params: {
q: this.search,
apikey: "",
},
});
this.items = response.data.items;
console.log(this.items);
},
away() {
console.log("clicked away");
this.show = false;
},
clickCard(item, target) {
console.log(item);
console.log(target);
this.show = false;
this.show2 = true;
},
updateCard(item, target) {
console.log(item);
console.log(target);
},
//Method That Take and wait for the Input
waitForSearch() {
// this.search = "";
clearTimeout(this.timerId);
this.timerId = setTimeout(() => {
this.getBooks();
}, 1000);
},
},
Content.vue i just used slot nothing else
<div class="container">
<div class="row">
<slot name="cardContent"></slot>
</div>
</div>
HelloWorld.vue
html
<div class="menu pointerCursor hide">
<slot name="contentHandler"></slot>
</div>
I try many times but failed. Any leads, please?
What I would try is to keep a record of the index that I want to show.
So what you could do is the following:
1.Change the code calling ClickCard
<div #click="clickCard(item, index)" class="containerForI">
2.Assign the value of index to a component variable
clickCard(item, index) {
console.log(item);
this.indexToShow = index;
this.show = false;
this.show2 = true;
},
3.Initialize the aforementioned variable in your component
data() {
return {
BASE_URL: "https://www.googleapis.com/books/v1/volumes",
indexToShow: null,
...
4.Finally, check if the currently selected index is the one to show
<Content v-show="indexToShow === null || indexToShow === index"
If you want to show all items, after showing only 1, you will have to set indexToShow to null. The Content component is checking for it.
How can I tigger the dialog from main file? I have no idea how to tigg ConfirmationDialog value "dislog" to true. Or any other method to do it? Dont want to group the code as a one file.
That is a component called ConfirmationDialog.vue
<template>
<v-layout row justify-center>
<v-btn color="primary" dark #click.native.stop="dialog = true">Open Dialog</v-btn>
<v-dialog v-model="dialog" max-width="290">
<v-card>
<v-card-title class="headline">Use Google's location service?</v-card-title>
<v-card-text>Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="green darken-1"
flat="flat"
#click.native="dialog = false"
>Disagree</v-btn>
<v-btn color="green darken-1" flat="flat" #click.native="dialog = false">Agree</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
export default {
data() {
return {
dialog: false
}
}
}
</script>
Main File:
<template>
<div class="row">
<div class="col-12">
<confirmationDialog></confirmationDialog>
</div>
</div>
</template>
<script>
import confirmationDialog from '../confirmationDialog'
export default {
data() {
return {}
},
components: {
confirmationDialog
},
methods: {
update() {
// Todo: Tigger Confirmation Dislog
}
},
}
</script>
Add a prop called show to the child component (confirmationDialog ) and bind to a parent property :
confirmationDialog
...
<script>
export default {
props:['show'],
data() {
return {
dialog: false
}
},
mounted(){
this.dialog=this.show;
}
}
</script>
Main
<template>
<div class="row">
<div class="col-12">
<confirmationDialog :show="showDialog"></confirmationDialog>
</div>
</div>
</template>
<script>
import confirmationDialog from '../confirmationDialog'
export default {
data() {
return {
showDialog:false,
}
},
components: {
confirmationDialog
},
methods: {
update() {
this.showDialog=true;
}
},
}
</script>
I want to create a reusable v-dialog with vuetify,
I created the BaseModal:
<v-dialog
v-model="inputVal"
:hide-overlay="overlay"
:max-width="width"
>
<v-card>
<v-toolbar flat>
<v-btn color="black" dark icon right #click="closeModal">
<v-icon>mdi-close</v-icon>
</v-btn>
<v-spacer></v-spacer>
<v-toolbar-title id="toolbar-title">{{ title }}</v-toolbar-title>
</v-toolbar>
<v-card-title class="headline">
<!--Card Title-->
</v-card-title>
<v-card-text>
<slot name="content"></slot>
</v-card-text>
</v-card>
</v-dialog>
InputVal as computed and dataBindingName as props :
computed: {
inputVal: {
get() {
return this.dataBindingName;
},
set(val) {
this.$emit("input", val);
}
}
},
props: {
dataBindingName: {
Boolean,
required: false
},}
I'm calling this base component in another component like this:
<modal-simple
:dataBindingName="dataBindingName"
title="Nouveau"
width="418"
>
<template v-slot:content>
<add-time-sheet-form />
</template>
</modal-simple>
My problem now is how to implement correctly the closeModal and how to implement a button inside that close the modal and open a new modal
Part 1. Modal component.
Take care that you should not use v-model="dialog". As already described in this answer, you need to replace it with :value and #input.
Moreover, you should not mutate dialog prop directly, that's why you need to emit close-dialog event when you need to close your modal.
<template>
<v-dialog
:value="dialog"
#input="$emit('input', $event)"
max-width="500px"
persistent
>
<v-card>
<v-card-title>
... dialog header ...
</v-card-title>
<v-card-text>
... dialog content ...
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn #click="close">
Close
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
props: {
editedId: Number,
dialog: Boolean,
},
methods: {
close() {
this.$emit("close-dialog");
},
},
};
</script>
Part 2. Parent component.
Imagine you want to use your component when adding or editing entities.
You need to implement two methods: addItem and editItem to open your dialog. You also need to pass extra entity props (editedId in my example), dialog prop with sync modifier and close-dialog event handler that was emitted from modal component.
<template>
<div>
<v-toolbar flat color="white">
<v-spacer />
<edit-modal
:edited-id="editedId"
:dialog.sync="dialog"
#close-dialog="
editedId = null;
dialog = false;
"
/>
<v-btn color="primary" dark class="mb-2" #click="addItem">
Add entity
</v-btn>
</v-toolbar>
<v-data-table :items="items" :headers="headers">
<template v-slot:item="props">
<tr>
<td>{{ props.item.name }}</td>
<td class="justify-center text-center">
<v-icon small class="mr-2" #click="editItem(props.item)">
edit
</v-icon>
</td>
</tr>
</template>
</v-data-table>
</div>
</template>
<script>
import Dialog from "./ReusableDialog";
export default {
components: {
"edit-modal": Dialog,
},
data() {
return {
items: [
... some items ...
],
headers: [
... some headers ...
],
editedId: null,
dialog: false,
};
},
methods: {
addItem() {
this.dialog = true;
},
editItem(item) {
this.editedId = item.id;
this.dialog = true;
},
},
};
</script>
Part 3. Modifying modal to reopen automatically.
In this example, modal component will reopen automatically until editedId will not be set.
In modal component:
...
close() {
this.$emit("close-dialog");
if (this.editedId === null) {
this.$emit("open-dialog");
}
},
...
In parent component:
...
<edit-modal
... some props ...
#open-dialog="
editedId = 999;
dialog = true;
"
/>
...
There is a codesandbox with working example.
I want to update the likes for the specific comment
this is the parent component Commnet.vue
<template>
<v-list class="list" color="white" three-line>
<template v-for="cmnt in comments" class="mb-2">
<v-card color="transparent" class=" text-no-wrap" :key="cmnt._id">
<v-list-item class="item" :key="cmnt._id">
<v-list-item-avatar>
<v-img :src="cmnt.author.image"></v-img>
</v-list-item-avatar>
<v-list-item-content class="black--text">
<v-list-item-title>{{
cmnt.author.first_name + " " + cmnt.author.last_name
}}</v-list-item-title>
<v-list-item-subtitle class="black--text" v-html="cmnt.comment">
{{ cmnt.comment }}
</v-list-item-subtitle>
</v-list-item-content>
<v-card class="like-count">
<v-icon color="blue">mdi-thumb-up </v-icon>
<Likes :_id="cmnt._id"/>
</v-card>
</v-list-item>
</v-card>
<v-card
:key="cmnt._id"
outlined="true"
color="transparent"
class="ml-6"
>
</template>
and this is the child component inside comment component it has it is own state completely separated form the parent.
Like.vue
<template>
<div>
<v-card >
</v-card>
{{likes.length}}
</div>
</template>
<script>
import axios from "axios";
import io from "socket.io-client";
export default {
name:"Likes",
created:async function(){
axios.get(`comment/${this._id}`)
.then(results=>{
if (results.data){
this.likes =results.data;
}
})
.catch(err=> console.log(err));
let url = "";
if (process.env.NODE_ENV === "production") {
url = "/";
} else {
url = "http://localhost:5000";
}
this.socket = io(url);
this.socket.on("receive-like",async (data)=>{
console.log(data)
this.new_like= data;
console.log(this.new_like)
const el = this.likes.find(el => el._id === this.new_like._id)
if (el){
const index = this.likes.indexOf(el);
this.$forceUpdate()
return this.likes.splice(index,1)
}else{
this.likes.push(this.new_like);
console.log(this.likes)
this.$forceUpdate()
}
})
},
mounted:async function(){
},
props:{
_id:{
type: String
}
},
data:()=>({
user:{},
likes:[],
new_like:{}
}),
computed:{
},
}
</script>
so when clicking like the new like object get pushed to the array of likes for the concerned comment but likes for all comments get updated at ones.
in case somebody is wondering I just made adding the new like object conditional
if(data.comment._id === this._id)