Why my Vuetify's Datepicker doesn't work? - vue.js

I'm new to vuejs + vuetify. I am using a datepicker to filter a datatable. The filtering part is working, however, when I clear the field the table does not return to original form. I tested using the html's input-date and worked perfectly. What am I doing wrong?
This is the datepicker component:
<template>
<v-menu
ref="menu"
v-model="menu"
:close-on-content-click="false"
transition="scale-transition"
offset-y
max-width="290"
min-width="290"
>
<template v-slot:activator="{ on }">
<v-text-field
clearable
dense
color="#15C98A"
outlined
v-model="computedDataFormatada"
label="data inicio"
append-icon="mdi-calendar-outline"
readonly
v-on="on"
></v-text-field>
</template>
<v-date-picker
v-model="date"
#input="dataEscolhida"
locale="pt"
color="#15C98A"
no-title
></v-date-picker>
</v-menu>
</template>
<script>
export default {
name:'DataPicker',
props:['label'],
data() {
return {
date: null,
menu: false,
};
},
computed: {
computedDataFormatada () {
return this.formataData(this.date)
},
},
methods: {
dataEscolhida() {
this.$emit('selecionado',this.computedDataFormatada);
this.menu = false;
},
formataData(date) {
if (!date) return null;
const [year, month, day] = date.split("-");
return `${day}/${month}/${year}`;
}
}
};
</script>
This is the way I'm filtering:
<v-data-table
fixed-header
single-select
item-key="id"
:headers="headers"
:items="customFilter"
:items-per-page="5"
class="elevation-1"
></v-data-table>
computed:{
customFilter(){
let startDate = this.dataInicioFiltro;
let endDate = this.dataFimFiltro;
return _.filter(this.grupos, (function (info) {
let date = info.data;
if ( (_.isNull(startDate) && _.isNull(endDate))||(_.isEmpty(startDate) && _.isEmpty(endDate)))
return true;
else if((!_.isEmpty(startDate) && _.isEmpty(endDate)))
return date ===startDate;
else if((_.isEmpty(startDate) && !_.isEmpty(endDate)))
return date ===endDate;
else
return (date >= startDate && date <= endDate);
}))
}
}
And this is how I'm using the component in the view:
<data-filtro label="data inicial" #selecionado="dataInicioFiltro=$event" />
I'm also using the lib lodash.

Ok everyone, I finally solved it out! Just have to use the event click:clear

Related

props date is null on submit with v-date-picker and Vue 2.6

Hello i'm trying to get the props date from children component Datepicker to the parent component Form but everytime when i submit i have date:null in console log.
I don't understand how to fecth it please ?
i'm using Vue 2.6 to use Vuetify with this datepicker
https://vuetifyjs.com/en/components/date-pickers/#formatting
here is the code :
<template>
<v-container>
<v-row>
<v-col cols="12" lg="6">
<v-menu v-model="menu" :close-on-content-click="false" transition="scale-transition" offset-y max-width="290px" min-width="auto">
<template v-slot:activator="{ on, attrs }">
<v-text-field v-model="computedDateFormatted" persistent-hint prepend-icon="mdi-calendar" readonly v-bind="attrs" v-on="on"></v-text-field>
</template>
<v-date-picker v-model="date" no-title #input="menu = false"></v-date-picker>
</v-menu>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
name: "DatePicker",
// props: { date: { type: String } },
data: (vm) => ({
date: new Date(Date.now() - new Date().getTimezoneOffset() * 60000).toISOString().substr(0, 10),
dateFormatted: vm.formatDate(new Date(Date.now() - new Date().getTimezoneOffset() * 60000).toISOString().substr(0, 10)),
menu: false,
}),
computed: {
computedDateFormatted() {
return this.formatDate(this.date)
},
},
watch: {
date() {
this.dateFormatted = this.formatDate(this.date)
},
},
methods: {
formatDate(date) {
if (!date) return null
const [year, month, day] = date.split("-")
return `${month}/${day}/${year}`
},
parseDate(date) {
if (!date) return null
const [month, day, year] = date.split("/")
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`
},
},
}
</script>
<style lang="scss" scoped></style>
and the form component
<template>
<div>
<v-main>
<v-container class="white form-container">
<v-form
method="POST"
ref="form"
lazy-validation
#submit.prevent="postForm">
<!-- Datepicker -->
<v-row no-gutters>
<v-col sm="6" md="5" lg="5" class="bottom-row">
<v-label>Add a date</v-label>
<DatePicker :date="date" />
</v-col>
</v-row>
</v-form>
</v-container>
</v-main>
</div>
</template>
<script>
import axios from "axios"
import DatePicker from "./DatePicker.vue"
export default {
name: "Form",
components: {
DatePicker,
},
data() {
return {
date: null,
}
},
methods: {
async postForm(event) {
/**
* #param json
*/
const data = {
date: this.date,
}
const result = await axios.post("url", data)
console.log("Post date", data)
event.preventDefault()
},
},
}
</script>
<style lang="scss" scoped></style>

How can i add parent-child group checkbox to on vuetify datatable?

When i use the vuetify data datable group header feature and
when the top group checkbox is selected, i want the checkboxes below it to be selected as well.
Here is the code.
https://codepen.io/ersin-g-ven-/pen/LYdeWor?editors=1010
<div id="app">
<v-app id="inspire">
<v-data-table
:headers="headers"
:items="desserts"
item-key="name"
sort-by="name"
group-by="category"
class="elevation-1"
show-select
show-group-by
>
<template v-slot:[`group.header`]="{items}">
<th colspan="2">
<v-checkbox
v-model="selected"
:label="items[0].category"
></v-checkbox>
</th>
</template>
</v-data-table>
</v-app>
</div>
Just came across your post. I think the combination of v-treeview with selection-type="leaf" can do the trick.
Check the documentation on: https://vuetifyjs.com/en/api/v-treeview/#props-selection-type
and see how it works: https://vuetifyjs.com/en/components/treeview/#selection-type
Using of the "v-model" with "watch" has worked for me:
<template v-slot:group.header="{group, items}">
<th colspan="4">
<v-checkbox
:label="items[0].category"
:value="group"
v-model="selected_groups"
>
</v-checkbox>
</th>
</template>
...
data() {
...
selected: [],
selected_groups: []
}
watch: {
selected_groups(node_new, node_old) {
if(node_new.length < node_old.length) {
let dif = node_old.filter(x => !node_new.includes(x))[0]
this.selected = this.selected.filter(item => { return !Object.values(item).includes(dif) })
} else if (node_new.length > node_old.length) {
this.items_arr.forEach(item => {
if(Object.values(item).includes(node_new.at(-1))) {
this.selected.push(item)
}
})
} else if (node_new.length == node_old.length) {
return this.selected
}
},
selected(selected_new, selected_old) {
if(selected_new.length < selected_old.length) {
let dif_NODE = selected_old.filter(x => !selected_new.includes(x))[0][this.groupable_col]
let arr_NODEs = []
selected_new.forEach(item => { arr_NODEs.push(item[this.groupable_col]) })
if(!arr_NODEs.includes(dif_NODE)) {
this.selected_groups= this.selected_groups.filter(item => item != dif_NODE)
}
} else if(selected_new.length > selected_old.length) {
if(!this.selected_groups.includes(selected_new.at(-1)[this.groupable_col])) {
this.selected_groups.push(selected_new.at(-1)[this.groupable_col])
}
}
}
}

How to insert text search field for each table header for multi search function dynamically with v-for?

In order to achieve for multi search function we add a search field at each header with v-slot where we define the header name directly. For example:
<template v-slot:header.NAME="{ header }">
{{ header.text }}
<v-menu offset-y :close-on-content-click="false">
<template v-slot:activator="{ on, attrs }">
<v-text-field v-bind="attrs" v-on="on"
v-model="nameSearch"
class="pa"
type="text"
></v-text-field>
</template>
</v-menu>
</template>
Now I have around 50 headers for my data table. My idea is to render dynamically. I tried with v-for but neither it renders and or give any error. Code below:
<template v-for="(x, index) in this.headers" slot="headers" slot-scope="props">
{{ props.x.text }}
<v-menu offset-y :close-on-content-click="false" :key="index">
<template v-slot:activator="{ on, attrs }">
<v-text-field v-bind="attrs" v-on="on"
v-model="searchObj"
class="pa"
type="text"
></v-text-field>
</template>
</v-menu>
</template>
what did i missed here ? or it is completely wrong way i went ?
Below is the full code:
<template>
<v-app class="main-frame">
<v-main>
<v-data-table
:headers="headers"
:items="filteredData"
>
<template v-slot:header.NAME="{ header }">
{{ header.text }}
<v-menu offset-y :close-on-content-click="false">
<template v-slot:activator="{ on, attrs }">
<v-text-field v-bind="attrs" v-on="on"
v-model="nameSearch"
class="pa"
type="text"
></v-text-field>
</template>
</v-menu>
</template>
<template v-slot:header.DEPARTMENT="{ header }">
{{ header.text }}
<v-menu offset-y :close-on-content-click="false">
<template v-slot:activator="{ on, attrs }">
<v-text-field v-bind="attrs" v-on="on"
v-model="departmentSearch"
class="pa"
type="text"
></v-text-field>
</template>
</v-menu>
</template>
</v-data-table>
</v-main>
</v-app>
</template>
<script>
import axios from "axios";
}
export default {
name: 'Home',
data() {
return {
/* Table data */
headers: []
allData: [],
/* Column Search */
nameSearch: '',
departmentSearch: ''
}
},
computed: {
filteredData() {
let conditions = [];
if (this.nameSearch) {
conditions.push(this.filterName);
}
if (this.departmentSearch) {
conditions.push(this.filterDepartment);
}
if (conditions.length > 0) {
return this.allData.filter((data) => {
return conditions.every((condition) => {
return condition(data);
})
})
}
return this.allData;
}
},
mounted () {
this.getAllData()
},
methods: {
getAllData() {
this.allData = []
axios
.get("http://localhost:5001/"}
.then(res => {
if (res.status === 200) {
if (res.data === 0) {
console.log("Something is wrong !!!")
} else {
this.allData = res.data["allData"]
this.headers = res.data["allDataHeaders"]
}
}
}).catch(error => {
console.log(error);
})
},
filterName(item) {
return item.NAME.toLowerCase().includes(this.nameSearch.toLowerCase())
},
filterDepartment(item) {
return item.DEPARTMENT.toLowerCase().includes(this.departmentSearch.toLowerCase())
},
}
}
</script>
I have found the solution myself:
<template v-for="(header, i) in headers" v-slot:
[`header.${header.value}`]="{ }">
<div #click.stop :key="i">
{{ header.text }}
<v-text-field :key="i"
v-model="multiSearch[header.value]"
class="pa"
type="text"
:placeholder="header.value"
prepend-inner-icon="mdi-magnify"
></v-text-field>
</div>
</template>
In data, I have an empty object called:
searchObj: {}
and in computed method, i have the following method:
filteredData() {
if (this.searchObj) {
return this.allData.filter(item => {
return Object.entries(this.searchObj).every(([key, value]) => {
return (item[key] || '').toLowerCase().includes(value.toLowerCase())
})
})
} else {
return this.allData
}
},
Full solution below:
<template>
<v-app class="main-frame">
<v-main>
<v-data-table
:headers="headers"
:items="filteredData"
>
<template v-for="(header, i) in headers" v-slot:
[`header.${header.value}`]="{ }">
{{ header.text }}
<div #click.stop :key="i">
<v-text-field :key="i"
v-model="multiSearch[header.value]"
class="pa"
type="text"
:placeholder="header.value"
prepend-inner-icon="mdi-magnify"
></v-text-field>
</div>
</template>
</v-data-table>
</v-main>
</v-app>
</template>
<script>
import axios from "axios";
}
export default {
name: 'Home',
data() {
return {
/* Table data */
headers: []
allData: [],
searchObj: {},
}
},
computed: {
filteredData() {
if (this.searchObj) {
return this.allData.filter(item => {
return Object.entries(this.searchObj).every(([key, value]) => {
return (item[key] ||'').toLowerCase().includes(value.toLowerCase())
})
})
} else {
return this.allData
}
},
},
mounted () {
this.getAllData()
},
methods: {
getAllData() {
this.allData = []
axios
.get("http://localhost:5001/"}
.then(res => {
if (res.status === 200) {
if (res.data === 0) {
console.log("Something is wrong !!!")
} else {
this.allData = res.data["allData"]
this.headers = res.data["allDataHeaders"]
}
}
}).catch(error => {
console.log(error);
})
},
}
}
</script>

vuetify dropdown get data's by using vue Infinite loading

I tried to get data for my vuetify drop down list by using vue-infinite-loading. function is not calling automatically.
Below is my code
<v-menu offset-y offset-x bottom left max-height="500" min-width="400" max-width="450">
<template v-slot:activator="{ on }">
<el-badge :value="unReadMessage" :hidden="hidden" class="item">
<v-icon color="white" v-on="on">notifications</v-icon>
</el-badge>
</template>
<v-list v-for="(item, index) in notification_data" :key="index">
<v-list-tile>
<v-list-tile-content>
<v-list-tile-title>{{item.title}}</v-list-tile-title>
<v-list-tile-sub-title>{{item.description}}</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
<infinite-loading :identifier="infiniteId" #infinite="infiniteHandler" ref="infiniteLoading"></infinite-loading>
</menu>
Below is written in script. I already imported this "import InfiniteLoading from 'vue-infinite-loading';"
When i put the infinite loader out of the menu, its working but it shown the value out of the list
<script>
methods: {
infiniteHandler($state) {
this.loading = true;
this.axios.get(api, {
params: {
page: this.page,
},
})
.then(({data}) => {
if (data.next !== null) {
this.page += 1;
this.notification_data = this.notification_data.concat(data.results);
this.loading = false;
$state.loaded();
}
else {
this.loading = false;
this.notification_data = this.notification_data.concat(data.results);
$state.complete();
}
})
.catch(error => {
this.$notify({
type: 'error',
title: 'Error!',
message: error,
});
});
},
},
components: {
InfiniteLoading
}
</script>

v-checkboxes are true when the page is loaded

I am doing form validation in vuelidate. I have a group of checkboxes. There are other fields also in the form. I want to show the success-messages of the checkbox only when a checkbox is checked. But the success-messages are showing when the page loads even when the checkboxes are not checked. What is wrong with my code. Here is my code:
<template>
<v-dialog persistent max-width="75%" v-model="dialog">
<v-btn round color="secondary" slot="activator">New Enquiry</v-btn>
<v-card>
<v-card-text>
<v-form ref="enquiryForm">
<v-container fluid grid-list-lg>
<v-layout row wrap>
<v-flex xs6>
<span class="title">Prefrences</span>
<v-layout row wrap>
<v-flex xs6>
<v-checkbox
v-for="( value, index ) in preferencesData"
:key="index"
v-model="enquiryForm.preferences"
:label="value"
:value="index"
required
:success="!!enquiryForm.preferences"
:success-messages="(!!enquiryForm.preferences) ? 'Ok' : ''"
:error-messages="fieldErrors('enquiryForm.preferences')"
#change="$v.enquiryForm.preferences.$touch()"
#blur="$v.enquiryForm.preferences.$touch()"
></v-checkbox>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-container>
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn flat lg color="secondary" #click="close">Cancel</v-btn>
<v-btn flat lg color="secondary" #click="submit">Submit</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<script>
import { mapGetters } from 'vuex';
import validationMixin from '#/mixins/validationMixin';
import { required } from 'vuelidate/lib/validators'
import moment from 'moment';
const defaultFormData = {
date: moment().format(),
preferences: []
}
export default {
mixins: [ validationMixin ],
validations: {
enquiryForm: {
preferences: { required }
}
},
validationMessages: {
enquiryForm: {
preferences: {
required: 'Please select at least one.'
}
}
},
data ( ) {
return {
dialog: false,
enquiryForm: Object.assign({}, defaultFormData),
preferencesData: [
'Furnished',
'SemiFurnished',
'UnFurnished'
]
}
},
computed: {
...mapGetters({
projects: 'projects',
cpexecutives: 'cpexecutives'
})
},
mounted ( ) {
this.$store.dispatch('fetchProjects');
this.$store.dispatch('getUsers');
this.clearForm();
},
methods: {
clearForm ( ) {
this.$v.$reset();
this.enquiryForm = Object.assign({}, defaultFormData);
},
submit ( ) {
this.$v.$touch()
this.$store.dispatch('addEnquiry', {
date: moment().format(),
preferences: this.enquiryForm.preferences
})
.then( ( result ) => {
this.close();
} )
.catch( ( err ) => {
console.log( err );
} )
},
close ( ) {
this.clearForm();
this.dialog = false;
}
}
}
</script>
I tried:
:success="!!enquiryForm.preferences && !$invalid"
:success-messages="(!!enquiryForm.preferences && !$invalid) ? 'Ok' : ''"
and
:success="!!enquiryForm.preferences && !$v.$invalid"
:success-messages="(!!enquiryForm.preferences && !$v.$invalid) ? 'Ok' : ''"
but that did not help.
I managed to do it
:success="!!enquiryForm.preferences && !$v.enquiryForm.preferences.$invalid"
:success-messages="(!!enquiryForm.preferences && !$v.enquiryForm.preferences.$invalid) ? 'Ok' : ''"
But, I want to show the success message 'Ok' and error message only once below the checkboxes. How do I do it?