How can I multiple datepicker modal in vuetify? - vue.js

My vue component like this :
<template>
<v-row>
<v-col cols="12" sm="6" md="4">
<v-dialog
v-for="(item, i) in test" :key="i"
ref="dialog"
v-model="modal"
:return-value.sync="item.date"
persistent
width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="item.date"
label="Picker in dialog"
prepend-icon="event"
readonly
v-on="on"
></v-text-field>
</template>
<v-date-picker v-model="date" scrollable>
<div class="flex-grow-1"></div>
<v-btn text color="primary" #click="modal = false">Cancel</v-btn>
<v-btn text color="primary" #click="$refs.dialog.save(item.date)">OK</v-btn>
</v-date-picker>
</v-dialog>
</v-col>
</v-row>
</template>
<script>
export default {
data: () => ({
test: [
{ id: 1, date: new Date().toISOString().substr(0, 10) },
{ id: 2, date: new Date().toISOString().substr(0, 10) },
],
modal: false,
}),
}
</script>
multiple datetimepicker doesn't work properly
if i click ok button in the modal, there exist error like this :
[Vue warn]: Error in v-on handler: "TypeError: _vm.$refs.dialog.save is not a function"
How can I solve this problem?

First off, you need to return the whole object from the dialog, not just the date. With :return-value.sync="item.date", the objects in test will have only date as their only property. Your date picker also has a wrong binding.
<v-dialog
v-for="(item, i) in test" :key="i"
ref="dialog"
v-model="modal"
:return-value.sync="item"
persistent
width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="item.date"
label="Picker in dialog"
prepend-icon="event"
readonly
v-on="on"
></v-text-field>
</template>
<v-date-picker v-model="item.date" scrollable>
<div class="flex-grow-1"></div>
<v-btn text color="primary" #click="modal = false">OK</v-btn>
</v-date-picker>
</v-dialog>

Related

Vuetify v-dialog would not open - :value property does not work

I just tried to create a separate form using Vue and vuetify's v-dialog. Unfortunately, once taken into separate component the thing stopped working without any error.
Here's the code to my component:
<template>
<v-dialog :value="dialogOpen" persistent>
<template v-slot:activator="{ props }">
<v-btn color="primary" v-bind="props">Add new</v-btn>
</template>
<v-card>
<v-card-title>
<span class="text-h5">Subscriber</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6">
<v-text-field v-model="activeSubscriber.name" label="Name" required></v-text-field>
</v-col>
<v-col cols="12" sm="6">
<v-text-field v-model="activeSubscriber.email" label="Email" required></v-text-field>
</v-col>
<v-col cols="12" sm="6">
<v-select
v-model="activeSubscriber.state"
:items="['active', 'unsubscribed', 'junk', 'bounced', 'unconfirmed']"
label="State*"
required>
</v-select>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue-darken-1" variant="text">
Close
</v-btn>
<v-btn color="blue-darken-1" variant="text" #click="createSubscriber(activeSubscriber)">
Save
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
name: 'SubscriberForm',
props: {
id: null,
dialogOpen: false,
},
methods: {
createSubscriber(subscriber) {
this.$store.dispatch('subscribers/createSubscriber', subscriber).then(() => this.dialogOpen = false).then(() => alert(1));
}
},
watch: {
id: function(newId) {
if (newId !== null) {
this.$store.dispatch('subscribers/getSubscriber', newId);
}
},
},
computed: {
...mapGetters('subscribers', ['activeSubscriber']),
}
}
</script>
Basically, the only thing that I changed compared to examples on their website was switch v-model to :Value because we are actually passing the properties to the component.
The component is called like that
<SubscriberForm :id="subscriberId" :dialog-open="dialogOpen"/>
....
methods: {
openEditModal(id) {
this.subscriberId = id;
this.dialogOpen = true;
},
},
I tried watching the property dialogOpen and it gets passed perfectly fine.
What could be the issue?
UPDATE: tried the top voted solution at vuetify: programmatically showing dialog
It resolved the issue, however broke the activator button. So that does not fly as well

How to trigger vuetify dialog with vuetify's tab instead of a button

I'm trying to trigger a vuetify dialog with vuetify's tabs. I am not sure how to achieve that. I have two components, Tabs.vue and Dialog.vue.
From vuetify, the Tabs.vue component is:
<template>
<v-card>
<v-tabs
v-model="tab"
background-color="deep-purple accent-4"
centered
dark
icons-and-text
>
<v-tabs-slider></v-tabs-slider>
<v-tab href="#tab-1">
Recents
<v-icon>mdi-phone</v-icon>
</v-tab>
<v-tab href="#tab-2">
Favorites
<v-icon>mdi-heart</v-icon>
</v-tab>
<v-tab href="#tab-3">
Nearby
<v-icon>mdi-account-box</v-icon>
</v-tab>
</v-tabs>
<v-tabs-items v-model="tab">
<v-tab-item
v-for="i in 3"
:key="i"
:value="'tab-' + i"
>
<v-card flat>
<v-card-text>{{ text }}</v-card-text>
</v-card>
</v-tab-item>
</v-tabs-items>
</v-card>
</template>
The Dialog component is:
<template>
<v-row justify="center">
<v-dialog
v-model="dialog"
persistent
max-width="600px"
>
<template v-slot:activator="{ on, attrs }">
<v-btn
color="primary"
dark
v-bind="attrs"
v-on="on"
>
Open Dialog
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline">User Profile</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
label="Legal first name*"
required
></v-text-field>
</v-col>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
label="Legal middle name"
hint="example of helper text only on focus"
></v-text-field>
</v-col>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
label="Legal last name*"
hint="example of persistent helper text"
persistent-hint
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
label="Email*"
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
label="Password*"
type="password"
required
></v-text-field>
</v-col>
<v-col
cols="12"
sm="6"
>
<v-select
:items="['0-17', '18-29', '30-54', '54+']"
label="Age*"
required
></v-select>
</v-col>
<v-col
cols="12"
sm="6"
>
<v-autocomplete
:items="['Skiing', 'Ice hockey', 'Soccer', 'Basketball', 'Hockey', 'Reading', 'Writing', 'Coding', 'Basejump']"
label="Interests"
multiple
></v-autocomplete>
</v-col>
</v-row>
</v-container>
<small>*indicates required field</small>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="blue darken-1"
text
#click="dialog = false"
>
Close
</v-btn>
<v-btn
color="blue darken-1"
text
#click="dialog = false"
>
Save
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
Note that I copied each component from vuetify directly. As you can see to trigger the dialog, vuetify gives the example of using a button which is within the Dialog.vue component, I will paste that part of the code below again:
<template v-slot:activator="{ on, attrs }">
<v-btn
color="primary"
dark
v-bind="attrs"
v-on="on"
>
Open Dialog
</v-btn>
</template>
It's using the v-slot:activator to trigger the dialog. However I'm not sure how I can use one of the tabs in Tabs.vue to trigger the dialog from Dialogs.vue instead. Thank you
i made a CodeSandbox for you. if this is what you wanted i will explain afterwards what i did. Check here
ok...
first let's check your structur.
You wrapped Dialog.vue in its own component, that means you need to toggle the Dialog On/Off mechanism from outside now, the parent(Tabs.vue).
Tabs.vue
<template>
<v-card>
<v-tabs
background-color="deep-purple accent-4"
centered
dark
icons-and-text
>
<v-tabs-slider></v-tabs-slider>
<v-tab href="#tab-1" #change="toggleDialog('recents')">
Recents
<v-icon>mdi-phone</v-icon>
</v-tab>
<v-tab href="#tab-2" #change="toggleDialog('favorites')">
Favorites
<v-icon>mdi-heart</v-icon>
</v-tab>
<v-tab href="#tab-3" #change="toggleDialog('nearby')">
Nearby
<v-icon>mdi-account-box</v-icon>
</v-tab>
</v-tabs>
<v-tabs-items>
<v-tab-item v-for="i in 3" :key="i" :value="'tab-' + i">
<v-card flat>
<v-card-text>{{ text }}</v-card-text>
</v-card>
</v-tab-item>
</v-tabs-items>
<Dialog <--------------------------- ADDING component Dialog.vue
:show-dialog="dialog" <----------- PROP the On/Off logic
:tab-controll="tabControll" <----- PROP the "which tab is selected"
#close-dialog="dialog = false" <-- TOGGLE Off on "close" button
#save-dialog="dialog = false" <--- TOGGLE Off on "save" button
/>
</v-card>
</template>
<script>
import Dialog from "#/components/Dialog";
export default {
components: {
Dialog,
},
data() {
return {
tab: 0,
dialog: false, <--------- CONTROLLS the On/Off mechanism inside Dialog.vue
tabControll: "None Tab",<- CONTROLLS which tab is selected in Dialog.vue
text: "some text i guess",
};
},
methods: {
toggleDialog(tab) {
this.tabControll = tab;
this.dialog = true;
},
},
};
</script>
<style>
</style>
each v-tab got his very own changed event, that's why you need to listen to it on each v-tab.
<v-tabs
background-color="deep-purple accent-4"
centered
dark
icons-and-text
>
<v-tabs-slider></v-tabs-slider>
<v-tab href="#tab-1" #change="toggleDialog('recents')"> <------- #change
Recents
<v-icon>mdi-phone</v-icon>
</v-tab>
<v-tab href="#tab-2" #change="toggleDialog('favorites')"> <------- #change
Favorites
<v-icon>mdi-heart</v-icon>
</v-tab>
<v-tab href="#tab-3" #change="toggleDialog('nearby')"> <------- #change
Nearby
<v-icon>mdi-account-box</v-icon>
</v-tab>
</v-tabs>
now lets look at the toggleDialog function
methods: {
toggleDialog(tab) {
this.tabControll = tab;
this.dialog = true;
},
},
it does nothing else then toggle the dialog in your data to true and sets a tabControll to let your Dialog.vue know which tab was clicked.
Dialog.vue
now we prepare Dialog.vue to handle the outside controlled behaviors.
<template>
<v-row justify="center">
<v-dialog v-model="dialog" persistent max-width="600px"> <--------- HERE
<v-card>
<v-card-title>
<span class="headline">User Profile - {{ tabControll }}</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="4">
<v-text-field label="Legal first name*" required></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
label="Legal middle name"
hint="example of helper text only on focus"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
label="Legal last name*"
hint="example of persistent helper text"
persistent-hint
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field label="Email*" required></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
label="Password*"
type="password"
required
></v-text-field>
</v-col>
<v-col cols="12" sm="6">
<v-select
:items="['0-17', '18-29', '30-54', '54+']"
label="Age*"
required
></v-select>
</v-col>
<v-col cols="12" sm="6">
<v-autocomplete
:items="[
'Skiing',
'Ice hockey',
'Soccer',
'Basketball',
'Hockey',
'Reading',
'Writing',
'Coding',
'Basejump',
]"
label="Interests"
multiple
></v-autocomplete>
</v-col>
</v-row>
</v-container>
<small>*indicates required field</small>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text #click="$emit('close-dialog')">
Close
</v-btn>
<v-btn color="blue darken-1" text #click="$emit('save-dialog')">
Save
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
export default {
data() {
return {
dialog: this.showDialog,
};
},
watch: {
showDialog: function () {
this.dialog = this.showDialog;
},
},
props: {
showDialog: {
type: Boolean,
default: false,
},
tabControll: {
type: String,
default: "none",
},
},
};
</script>
<style>
</style>
we stay consistent and we don't use the showDialog prop in our v-model="dialog", otherwise we got a warning that we mutate props without the knowing of the parent (Tabs.vue)
<v-dialog v-model="dialog" persistent max-width="600px">
instead we do bind the incoming prop data into our dialog inside data
data() {
return {
dialog: this.showDialog,
};
},
now we do not mutate props from outside and we just copy the state of the dialog which is handled from Tabs.vue
if you now click on a Tab the event will toggle this showDialog into true and this will change the dialog inside your data also to true and show the Dialog.
so far so good... now we need functionality to turn the dialog off again.
as i said a multiple times, mutating props is a bad thing, we fire an $emit and we tell Tabs.vue to close the dialog again.
<v-btn color="blue darken-1" text #click="$emit('close-dialog')">
Close
</v-btn>
<v-btn color="blue darken-1" text #click="$emit('save-dialog')">
Save
</v-btn>
back to
Tabs.vue
we listen to those custom events and we toggle the dialog = false
right here
<Dialog
:show-dialog="dialog"
:tab-controll="tabControll"
#close-dialog="dialog = false" <-- TOGGLE Off on "close" button
#save-dialog="dialog = false" <--- TOGGLE Off on "save" button
/>

How can I call the edit component within another file?

I have a project and this project is for the owners of the purchase for the purchase of cars and many other operations, but I have a table with several columns, and within these columns there is a column I listen to action and this column contains a button called Edit and I want when I click on the Edit button to be used The component of the modification within this file, how can I do this?
And it is the Edit file in which the Edit form is located.
Edit.vue:
<template>
<v-row justify="center">
<v-dialog v-model="editDialog" persistent max-width="1050px" height="400px">
<template v-slot:activator="{ on, attrs }">
<v-btn
fab
accent
class="grey lighten-1 margin pa-4"
dark
v-bind="attrs"
v-on="on"
>
<v-icon>
mdi-pencil
</v-icon>
</v-btn>
</template>
<v-card>
<v-layout>
<v-flex xs12>
<div class="myfont pl-5">
<v-card-title>
<span> Edit Car</span>
</v-card-title>
</div>
</v-flex>
</v-layout>
<v-divider xs12></v-divider>
<v-layout>
<v-flex xs12>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12">
<v-text-field
name="name"
label="Name"
id="name"
class="colorLabel"
v-model="editedName"
multi-line
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
name="priceOfSale"
label="Price Of Sale"
id="priceOfSale"
v-model="editedPrice"
class="colorLabel"
multi-line
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
name="numberOfSeats"
label="NumberOfSeats"
id="numberOfSeats"
v-model="editedNumberOfSeats"
multi-line
required
></v-text-field>
</v-col>
</v-row>
</v-container>
</v-card-text>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-layout>
<v-flex xs12>
<v-card-actions>
<v-btn class="myfont pl-5 text-right" text #click="onSaveChanges">
Save
</v-btn>
<v-btn
class="myfont pl-5 text-center"
text
#click="editDialog = false"
>
Cancel
</v-btn>
</v-card-actions>
</v-flex>
</v-layout>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapActions } from "vuex";
import ActionsTypes from "../store/types/actions-types";
export default {
props: ["car"],
data() {
return {
editedName: this.car.name,
editedPrice: this.car.price,
editedNumberOfSeats: this.car.seatsNumber,
};
},
methods: {
...mapActions({
editCarInformations: ActionsTypes.EDIT_CAR_ACTION,
}),
onSaveChanges() {
const UpdatedCar = { ...this.car };
UpdatedCar.name = this.editedName;
UpdatedCar.price = this.editedPrice;
UpdatedCar.seatsNumber = this.editedNumberOfSeats;
this.editCarInformations(UpdatedCar);
},
},
};
</script>
This file, in which there is a table containing several columns, and the last column is Action, which contains the Modify button, the Modify button, and when I press it, the universe of the amendment is called.
viewAllCars:
<template>
<v-app class="bg">
<v-container>
<v-card
class="mx-auto mt-5 pa-3"
max-width="100%"
id="limited-products"
:style="'border: 0px solid #D50000;'"
>
<v-btn class="red accent-4 color myfont pl-3" #click="onCreateCar">
evict Cashig
</v-btn>
<v-data-table
:headers="tableHeaders"
:items="loadedCarsGetter"
:page.sync="page"
:items-per-page="itemsPerPage"
hide-default-footer
class="elevation-1"
#page-count="pageCount = $event"
>
<template #[`item.actions`]="{ item }">
<v-btn icon #click="edit(item.id)">
<v-icon>mdi-pencil</v-icon>
</v-btn>
<v-btn icon #click="delete (item.id)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</template>
</v-data-table>
<!-- pagination -->
<div class="text-center pt-2">
<v-pagination v-model="page" :length="pageCount"></v-pagination>
<v-text-field
:value="itemsPerPage"
label="Items per page"
type="number"
min="-1"
max="15"
#input="itemsPerPage = parseInt($event, 10)"
class="pl-7 pr-7"
></v-text-field>
</div>
</v-card>
</v-container>
</v-app>
</template>
<script>
import { mapActions, mapGetters } from "vuex";
import ActionsTypes from "../../store/types/actions-types";
import GettersTypes from "../../store/types/getters-types";
export default {
data() {
return {
page: 1,
pageCount: 0,
itemsPerPage: 10
};
},
created() {},
computed: {
...mapGetters({
loadedCarsGetter: GettersTypes.GET_CAR_FORM_GETTER,
tableHeaders: GettersTypes.GET_HEADERS_TABLE_GETTER,
}),
},
mounted() {
// this.loadedCarsGetter();
this.loadedCarsAction();
},
methods: {
...mapActions({
editcardispatcher: ActionsTypes.EDIT_CAR_ACTION,
deletecardispatcher: ActionsTypes.DELETE_CAR_ACTION,
loadedCarsAction: ActionsTypes.GET_ALL_CAR_ACTION
}),
edit() {
this.editcardispatcher({});
},
delete(){
this.deletecardispatcher(
this.car.id
)
}
},
};
</script>
First of all, you don't need the "v-row" in the Edit.vue. Remove it.
As you have the button as the activator, you should just add the component as Avraham mentioned. But you need to know that there are some caveats with this approach
This is gonna be increasing the memory usage by the browser. As a separate instance of Edit.vue will be added to the DOM for each row in your table.
Each Edit.vue instance will preserve the data in it with the changes that the user might make. And you'll have to handle the data resets.
A better solution would be to add only one instance of Edit.vue and add/remove the component from the DOM using a v-if.
This will keep your table using one instance of Edit.vue, and the addition and removal of the component will handle the data reset.
Something like this
In the file that contains the v-data-table, update the template as follows
<template>
......
<v-data-table ...>
...
<template #[`item.actions`]="{ item }">
<v-btn icon #click="edit(item.id)">
<v-icon>mdi-pencil</v-icon>
</v-btn>
<v-btn icon #click="delete(item.id)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</template>
...
</v-data-table>
<edit :car="item" v-if="showEditDialog = true" #closed="showEditDialog = false" />
......
</template>
<script>
import Edit from 'Edit.vue'
export default {
components: { Edit },
data: () =({
item: {},
showEditDialog: false,
}),
methods: {
edit(item) {
this.item = item
this.showEditDialog = true
}
}
}
</script>
In your Edit.vue, add a watcher for the "editDialog" property to emit an event to remove the edit dialog from the DOM.
watch: {
editDialog(val){
if(!val)
this.$emit('closed')
}
}
And remove this part from the Edit.Vue
<template v-slot:activator="{ on, attrs }">
<v-btn
fab
accent
class="grey lighten-1 margin pa-4"
dark
v-bind="attrs"
v-on="on"
>
<v-icon>
mdi-pencil
</v-icon>
</v-btn>
</template>
Good luck.
You should import the Edit.vue component in the car viewer component and use it instead of the edit button:
...
<template #[`item.actions`]="{ item }">
<!-- Pass the item to the `car` prop -->
<edit :car="item" />
<v-btn icon #click="delete (item.id)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</template>
...
<script>
import Edit from 'Edit.vue' // make sure the path to the component is correct
export default {
components: { Edit },
...
};
</script>

Vuetify dynamic form inputs with datepickers

I'm trying to make a dynamic form inside a dialog but having an issue with datepickers values. each datepicker doesn't set its value
<v-col
cols="12"
sm="12"
md="12"
v-if="typeOfContact === 'flexible'"
>
<v-btn
elevation="2"
color="primary"
#click="pushContract"
>
Add Contract
</v-btn>
</v-col>
<v-row
v-for="(contract, counter) in contracts"
v-bind:key="counter"
>
<v-col
cols="12"
sm="3"
md="3"
v-if="typeOfContact === 'flexible'"
>
<v-dialog
ref="contractStartDateDialog"
v-model="contractStartDateModal"
:return-value.sync="contract.startDate"
persistent
width="290px"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
v-model="contract.startDate"
label="Start Date"
prepend-icon="mdi-calendar"
readonly
v-bind="attrs"
v-on="on"
>
</v-text-field>
</template>
<v-date-picker
v-model="contract.startDate"
scrollable
>
<v-spacer></v-spacer>
<v-btn
text
color="primary"
#click="contractStartDateModal = false"
>
Cancel
</v-btn>
<v-btn
text
color="primary"
#click="$refs.contractStartDateDialog[counter].save(contract.startDate)"
>
OK
</v-btn>
</v-date-picker>
</v-dialog>
</v-col>
<v-col
cols="12"
sm="3"
md="3"
v-if="typeOfContact === 'flexible'"
>
<v-dialog
ref="contractEndDateDialog"
v-model="contractEndDateModal"
:return-value.sync="contract.endDate"
persistent
width="290px"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
v-model="contract.endDate"
label="End Date"
prepend-icon="mdi-calendar"
readonly
v-bind="attrs"
v-on="on"
>
</v-text-field>
</template>
<v-date-picker
v-model="contract.endDate"
scrollable
>
<v-spacer></v-spacer>
<v-btn
text
color="primary"
#click="contractEndDateModal = false"
>
Cancel
</v-btn>
<v-btn
text
color="primary"
#click="$refs.contractEndDateDialog[counter].save(contract.endDate)"
>
OK
</v-btn>
</v-date-picker>
</v-dialog>
</v-col>
<v-col
cols="12"
sm="2"
md="2"
v-if="typeOfContact === 'flexible'"
>
<v-text-field
v-model="contract.PIP"
label="Periodically Increase"
suffix="%"
required
:rules="[required('Periodically Increase'), minLength('Periodically Increase', 1), maxLength('Periodically Increase', 2), isNumuric('Periodically Increase')]"
/>
</v-col>
<v-col
cols="12"
sm="3"
md="3"
v-if="typeOfContact === 'flexible'"
>
<v-text-field
v-model="contract.PIA"
label="Periodically Increase Amount"
suffix="K EGP"
required
:rules="[required('Periodically Increase Amount'), minLength('Periodically Increase Amount', 1), maxLength('Periodically Increase Amount', 15), isNumuric('Periodically Increase Amount')]"
/>
</v-col>
<v-col
cols="12"
sm="1"
md="1"
v-if="typeOfContact === 'flexible'"
>
<v-icon
small
class="mt-6"
color="primary"
#click="deleteContract(counter)"
>
mdi-trash-can-outline
</v-icon>
</v-col>
</v-row>
script:
export default {
name: "data-management",
data: () => ({
contractStartDateModal: false,
contractEndDateModal: false,
contracts: [
{
startDate: new Date().toISOString().substr(0, 10),
endDate: new Date().toISOString().substr(0, 10),
PIP: null,
PIA: null,
},
{
startDate: new Date().toISOString().substr(0, 10),
endDate: new Date().toISOString().substr(0, 10),
PIP: null,
PIA: null,
},
],
}),
methods: {
closeContracts () {
this.contractsDialog = false;
this.$nextTick(() => {
this.editedItem = Object.assign({}, this.defaultItem);
this.editedIndex = -1;
});
this.closeContractsModal = true;
},
pushContract() {
this.contracts.push({
startDate: new Date().toISOString().substr(0, 10),
endDate: new Date().toISOString().substr(0, 10),
PIP: null,
PIA: null,
});
},
deleteContract(counter){
this.contracts.splice(counter,1);
}
},
}
when I assign the first start date it changes the second row's start date. And if I change the start date of the second row it it says
VDialog.ts?d213:245 Uncaught RangeError: Maximum call stack size
exceeded.
You have nested your v-dialog in your v-for hence generating as many v-dialog as rows. Ideally it would be preferable to declare it outside your looped element.

Display status of toggle switch in vuetify data-table

I'm complet stuck and can't see to fix my issue. My goal is to display the status of the toggle switch in my Vuetify data-table.
It seems to work but each time I change the toggle switch the status of all lines get changed. And this isn't the idea. It needs to be for each specific line.
Small side note: Instead of "true" and "false" I would prefer "On" and "off"
When you propose a solution, would you mind also telling me what I'm doing wrong as this is the only way I will learn.
<template>
<v-card>
<v-data-table :headers="headers" :items="companies">
<template v-slot:top>
<v-toolbar flat>
<v-dialog v-model="dialog" max-width="850px">
<template v-slot:activator="{on}">
<v-btn color="primary" dark class="mb-2" v-on="on">Nieuw bedrijf</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline">{{ formTitle }}</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="6">
<v-text-field v-model="editedItem.name" label="Bedrijfsnaam"></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col cols="12" sm="6" md="6">
<v-switch v-model="switch1" flat :label="`Switch 1: ${switch1.toString()}`"></v-switch>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text #click="close">Annuleer</v-btn>
<v-btn color="blue darken-1" text #click="save">Bewaar</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar>
<v-divider class="mt-3" />
</template>
<template v-slot:item.portaal="{}">
<v-chip color="primary" v-text="switch1" dark></v-chip>
</template>
<template v-slot:item.actions="{ item }">
<v-icon small class="mr-2" #click="editItem(item)">mdi-pencil</v-icon>
<v-icon small text #click="showDeleteDialog(item)">mdi-delete</v-icon>
</template>
</v-data-table>
<v-dialog v-model="dialogDelete" max-width="500px">
<v-card>
<v-card-title>Delete</v-card-title>
<v-card-text>Weet je zeker dat je {{itemToDelete.name}} wenst te verwijderen?</v-card-text>
<v-card-actions>
<v-btn color="primary" text #click="dialogDelete = false">Annuleer</v-btn>
<v-btn color="primary" text #click="deleteItem()">Verwijderen</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-card>
</template>
Script
<script>
export default {
data: () => ({
headers: [
{ text: "Bedrijfsnaam", align: "start", value: "name" },
{ text: "Portaal", value: "portaal", sortable: false },
{ text: "Actions", value: "actions", sortable: false }
],
companies: [],
switch1: false,
dialog: false,
dialogDelete: false,
itemToDelete: {},
editedIndex: -1,
editedItem: {
name: ""
}
}),
computed: {
formTitle() {
return this.editedIndex === -1
? "Nieuw bedrijf"
: "Bewerk " + this.editedItem.name;
}
},
watch: {
dialog(val) {
val || this.close();
}
},
created() {
this.initialize();
},
methods: {
initialize() {
this.companies = [
{
name: "Bogaert SCA",
phone: "+32 50 64 68 62",
email: "marie34#daems.net",
website: "www.daems.net",
to: "http://www.bloomford.be",
location: "Brugge"
},
{
name: "Thomas BVBA",
phone: "+32 9 654 97 31 64",
email: "tess.claessens#charlier.org",
website: "www.charlier.org",
to: "http://www.rsca.be",
location: "Gent"
}
];
},
switch1(newValue) {
this.headers[5].value = newValue;
},
editItem(item) {
this.editedIndex = this.companies.indexOf(item);
this.editedItem = Object.assign({}, item);
this.dialog = true;
},
showDeleteDialog(item) {
this.itemToDelete = item;
this.dialogDelete = !this.dialogDelete;
},
deleteItem() {
const index = this.companies.indexOf(this.itemToDelete);
this.companies.splice(index, 1);
this.dialogDelete = false;
},
close() {
this.dialog = false;
setTimeout(() => {
this.editedItem = Object.assign({}, this.defaultItem);
this.editedIndex = -1;
}, 300);
},
save() {
if (this.editedIndex > -1) {
Object.assign(this.companies[this.editedIndex], this.editedItem);
} else {
this.companies.push(this.editedItem);
}
this.close();
}
}
};
</script>
You should bind the switch to portaal. Also switch1 should not be a method and a data property. The label doesn't have to be the same as the modal. just use a method for the on/off label...
<v-data-table :headers="headers" :items="companies">
<template v-slot:top>
<v-toolbar flat>
<v-dialog v-model="dialog">
<template v-slot:activator="{on}">
<v-btn color="primary" dark class="mb-2" v-on="on">Nieuw bedrijf</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline">{{ formTitle }}</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="6">
<v-text-field v-model="editedItem.name" label="Bedrijfsnaam"></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col cols="12" sm="6" md="6">
<v-switch v-model="editedItem.portaal" flat :label="switchLabel(editedItem.portaal)"></v-switch>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text #click="close">Annuleer</v-btn>
<v-btn color="blue darken-1" text #click="save">Bewaar</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar>
<v-divider class="mt-3" />
</template>
<template v-slot:item.portaal="{ item }">
<v-chip color="primary" v-text="switchLabel(item.portaal||false)" dark></v-chip>
</template>
<template v-slot:item.actions="{ item }">
<v-icon small class="mr-2" #click="editItem(item)">mdi-pencil</v-icon>
<v-icon small text #click="showDeleteDialog(item)">mdi-delete</v-icon>
</template>
</v-data-table>
switchLabel (bool) {
return bool?'on':'off'
},
https://codeply.com/p/tlXizKP4dD