How to keep vuetify date picker in sync with input? - vue.js

I have a v-date-picker similar to the one in Vuetify documentation. I'm using the one that allows you to type dates on the input, besides allowing to select a date on the picker (see the anchored link I shared).
The problem is, if you are typing a date on the input while the date picker is open, the date on the picker will not be updated. From the user perspective, it will seem as if the old date is still selected.
Note that I'm already subscribing to the #input event on my input field, updating the date picker date whenever a valid date is typed. This seems to be a refresh/redraw problem that the picker has, as the calendar will not update to the correct date. It has to be closed and opened again for it to be updated.
The example in Vuetify documentation also has this problem.
Any idea on how can I force the refresh/redraw of the date picker while it is open?
Thanks!

I was creating a CodePen to better show my problem (as #kissu requested) and found that I had a bug on my implementation. That was why the date picker was not being updated with the typed date.
Here is the working template code:
<v-menu
v-model="menu1"
: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="formattedDate"
label="Date"
prepend-icon="mdi-calendar"
v-bind="attrs"
v-on="on"
#input="dateTyped"
></v-text-field>
</template>
<v-date-picker v-model="date" no-title #input="datePicked"></v-date-picker>
</v-menu>
<p>Date inside the input field is in <strong>DD/MM/YYYY</strong> format</p>
And javascript code:
const App = {
template: "#app-template",
data: () => ({
menu1: false,
date: "2022-10-25",
formattedDate: "25/10/2022"
}),
methods: {
datePicked(date) {
if (!date) return;
this.formattedDate = this.formatDateForInput(date);
this.menu1 = false;
},
formatDateForInput(date) {
const [year, month, day] = date.split("-");
return `${day}/${month}/${year}`;
},
dateTyped(date) {
if (!date || date.length !== 10) return;
console.log(date);
this.date = this.formatDateForPicker(date);
},
formatDateForPicker(date) {
const [day, month, year] = date.split("/");
return `${year}-${month}-${day}`;
}
}
};
CodePen in case someone wants to check it out in action: https://codepen.io/mcarreira/pen/gOKOepQ

Related

current month not selected when go previous month and open the v-date-picker again

I am using vuetify date picker and it's inside a dialog box. When I open the dialog box for first time it's showing current month and if I go to previous month and close the dialog box, then reopen it, it still remain in the previous month. I need to avoid it. Each time when the calendar opens, it should be in the current month without user to navigate to current month manually.
<v-dialog v-model="isShow">
<v-date-picker
v-model="dates1"
:max="max"
:min="min"
readonly
range
color="primary"
></v-date-picker>
</v-dialog>
My date picker is as in above and is there any way to solve this issue?
You could bind <v-date-picker>.pickerDate to a local data property that is reset to the current date when the dialog is closed.
Create a data property named "pickerDate", and bind it to <v-date-picker>.pickerDate with the .sync modifier:
<template>
<v-date-picker :pickerDate.sync="pickerDate" />
</template>
<script>
export default {
data() {
return {
pickerDate: null,
}
}
}
</script>
Add a watcher on isShow to reset pickerDate when isShow is false (upon the dialog closing):
<script>
export default {
watch: {
isShow(isShow) {
if (!isShow) {
const today = new Date().toISOString().split('T')[0]
this.pickerDate = today
}
}
}
}
</script>
demo

How to change the behavior of clicking an option item of v-autocomplete

Scenario
When clicking an option item, natively, the v-autocomplete (with multiple prop) active its respective checkbox and keeps with the menu open, allowing you to continue selecting other items until you click out of the menu
Objective
What I would like is to change this behavior, when I clicked only in the checkbox, the native behavior is maintained, but when clicked specifically on the line, the menu is closed and trigger a function using the value of the selected item.
I imagine that it is necessary to use the slots but I really don't know how to use it or if this is the best way to obtain this new behavior.
Note
The vertical line is for concept demonstration purposes only, it is not necessary to include this line in the component.
As you said, you can do it using slots. The idea is to override items display to remove the clickable v-list-item underneath. The drawback is that you have to re-implement values selection.
You'll need a checkbox and two methods: isSelected and toggleItem.
Template section:
<v-autocomplete
v-model="values"
:items="items"
outlined
dense
chips
small-chips
label="Outlined"
multiple
>
<template #item="{ item }">
<v-list-item class="d-flex">
<div>
<v-simple-checkbox color="primary" :value="isSelected(item)" #click="toggleItem(item)" />
</div>
<div class="ml-2">{{ item }}</div>
</v-list-item>
</template>
</v-autocomplete>
Script section:
data: () => ({
items: ['foo', 'bar', 'fizz', 'buzz'],
values: ['foo', 'bar'],
}),
methods: {
isSelected(item) {
return this.values.includes(item);
},
toggleItem(item) {
if (this.values.includes(item)) {
this.values = this.values.filter(v => v !== item);
} else {
this.values.push(item);
}
}
}
Please take a look at this working example.

Access to a slot function inside a child component in VusJS

I'm trying to use tiptap. Actually it works, but what I'm trying to do is to access the "isActive" slot from outside the editor component, and I don't know how to do it.
Here is a codesandbox example: https://codesandbox.io/s/v07xnxo807?file=/src/App.vue
You see the Editor component is called from the App.vue. The buttons in the Editor component are activated depending on the "isActive" slot functions.
What I would like is to access this slot to get for example the value of isActive.bold() from the App.vue, in order to update the model of a "multiple button" you can find on Vuetify: https://vuetifyjs.com/fr-FR/components/button-groups/
Here is for example what I could have:
<editor-menu-bar :editor="editor" v-slot="{ commands, isActive }">
<v-btn-toggle
v-model="toggle_multiple"
dense
background-color="primary"
dark
multiple
class="my-2"
>
<v-btn :color="isActive.bold()?'red':'green'" #click="commands.bold">
<v-icon>mdi-format-bold</v-icon>
</v-btn>
<v-btn #click="commands.italic">
<v-icon>mdi-format-italic</v-icon>
</v-btn>
<v-btn #click="commands.strike">
<v-icon>mdi-format-strikethrough</v-icon>
</v-btn>
<v-btn #click="commands.underline">
<v-icon>mdi-format-underline</v-icon>
</v-btn>
<v-btn #click="commands.blockquote">
<v-icon>mdi-format-quote-open</v-icon>
</v-btn>
</v-btn-toggle>
</editor-menu-bar>
And the toggle_multiple would be computed depending on the different "isActive" function values.
I already tried:
computed: {
toggle_multiple: function () {
let t = []
if (editor) {console.log("Bold: "+editor.isActive.bold())}
return t
}
},
But I receive this error: error 'editor' is not defined
I'm open to any suggestion.
Thanks in advance.
Property isActive is stored in the tiptap instance (in your case it's this.editor):
In HTML:
<div>{{editor.isActive.bold()}}</div>
In JS:
<div>{{toggle_multiple}}</div>
computed: {
toggle_multiple () {
// Keep in mind, other properties like ".isActive.heading()" will be undefined
// until you import the extension for it.
// So the function "heading" below exists only if you're using that extension
// console.log(this.editor.isActive.heading({ level: 2 })
return this.editor.isActive.bold()
}
}

Vuetify v-rating events ~ click

I am using vuetifys v-rating component. I am displaying the current average rating using v-model. When a user clicks the rating component I want to update the current rating. This works good, the problem is that there will be no event emitted, when the current rating is equal to the rating the user want to give. This follows the docks, as the rating component does only emit an event when the input is changed. Any ideas how to emit an event when a star is clicked regardless if it is the same as the current one?
<v-rating
:readonly="isGuest"
color="yellow accent-4"
background-color="grey lighten-2"
v-model="averageRating"
hover
size="20"
dense
#input="handleRating"
></v-rating>
You can use item slot for handling rating change:
<v-rating v-model="rating">
<template v-slot:item="props">
<v-icon
:color="props.isFilled ? 'blue' : 'grey lighten-1'"
#click="handleRatingChange(props)"
>mdi-star
</v-icon>
</template>
</v-rating>
data: () => ({
rating: 3
}),
methods: {
handleRatingChange(props) {
console.log(props.index + 1)
this.rating = props.index + 1
}
}

v-autocomplete and setting user input as its value

I use vuetify in my project and need typeahead component. Sadly v-autocomplete implemented as combobox with filter, so it doesn't allow setting user input as v-model (or at least I can't find I way how to do so).
Could someone please explain me how to implement such functionality (maybe by another vuetify component)? I load items from server, but they are serve just as suggestions. Users need to have an ability to type and set any value they want to.
Here is a base example https://codepen.io/miklever/pen/oMZxzZ. The problem is that if I type any word that doesn't start with 'John' v-autocomplete clears it on blur. I've tried to set v-model manually and to add user input to array, but any of this methods has issues and doesn't work as expected.
<div id="app">
<v-app>
<v-content>
<v-container>
<p>Name: {{ select || 'unknown'}}</>
<v-autocomplete
:items="items"
:search-input.sync="search"
v-model="select"
cache-items
flat
hide-no-data
label="Name"
></v-autocomplete>
</v-container>
</v-content>
</v-app>
</div>
new Vue({
el: "#app",
data: () => ({
items: [],
search: null,
select: null,
commonNames: ["John", "John2", "John3"]
}),
watch: {
search(val) {
val && val !== this.select && this.querySelections(val);
}
},
methods: {
querySelections(v) {
setTimeout(() => {
this.items = this.commonNames.filter(e => {
return (e || "").toLowerCase().indexOf((v || "").toLowerCase()) > -1;
});
}, 500);
}
}
});
In Vuetify 1.1.7 Combobox has new feature which you can refer to.
Its on the Advance custom options.
had this same issue and solved it with the v-combobox it's kinda like the same as v-autocomplete so, you can just replace your tags with <v-combobox></v-combobox> or check the documentation here: https://vuetifyjs.com/en/components/combobox/#usage