Can I pass a parameter by pickerDate vuetify? - vue.js

My datepicker like this :
<v-date-picker v-model="date" scrollable :picker-date.sync="pickerDate">
The datepicker in loop
My script vue like this :
data: () => ({
date: new Date().toISOString().substr(0, 10),
pickerDate: null,
}),
watch: {
pickerDate (val) {
console.log(val)
},
},
In every loop, there exist a parameter id and I want to pass parameter id
I try like this :
<v-date-picker v-model="date" scrollable :picker-date.sync="pickerDate(id)">
But there exist error :
Syntax Error: SyntaxError: Unexpected token
How can I solve this problem?
Reference : https://vuetifyjs.com/en/components/date-pickers#date-pickers-react-to-displayed-month-year-change

You cannot pass parameters in picker-date, but still you can pass in Vuetify datepicker update:picker-date event
When you change the month in datepicker, it returns the value as 2019-10 if the selected month is October. If you change the month November then the value will be 2019-11 and id is what your passing on the iteration
<v-date-picker
v-model="date"
class="mt-4"
#update:picker-date="pickerUpdate($event, id)"
></v-date-picker>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
date: '2019-10-15',
id: 5,
}),
methods: {
pickerUpdate(val, id) {
// you can read the val --> 2019-10 for october, id what you are passing
// when you iterate with multiple date picker, you can set id's
// write your async call here
console.log('from picker update ' + val + ' id: ' + id );
},
},
})

Related

Custom vue component not updating on value change

I have a codepen at https://codepen.io/james-hudson3010/pen/QWgarbr which demonstrates the problem.
I am trying to create and use a custom checkbox component based on using v-btn and v-icon.
When I click on the checkbox, I get the input event and the data changes, but the look of the checkbox does not change. I am certain it is because the method I call to obtain the value is not "reactive". Therefore, upon a value change, there is not a rerender.
I need to call a method to obtain the value because obtaining the value can be complex and based upon which box was clicked. There is an unknown number of boxes.
However, there is some fundamental concept I a missing here, but I am not sure what it is.
What do I need to change in my code for this to work?
(no, I do not want to use v-checkbox...in part, this is for my own edification for how to create such things.)
Javascript
Vue.component('mybox', {
props: ['value'],
data() {
return {
selected: null,
}
},
template: `
<v-btn v-if="value" #click="clicked()" icon dense>
<v-icon color="#f9a602">check_box</v-icon>
</v-btn>
<v-btn v-else #click="clicked()" icon dense>
<v-icon color="#f9a602">check_box_outline_blank</v-icon>
</v-btn>
`,
methods: {
clicked() {
console.log( "clicked", this.selected, this.value );
this.selected = !this.value;
console.log( "clicked", this.selected, this.value );
this.$emit( "input", this.selected );
}
},
watch: {
selected() {
console.log("selected:", this.selected);
// this.$emit("input", this.selected);
},
}
});
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
boxvalues: [true, false],
},
methods: {
boxValueChanged( index ) {
console.log( "boxValueChanged", index, this.boxvalues[ index ] );
this.boxvalues[ index ] = !this.boxvalues[ index ];
console.log( "boxValueChanged", index, this.boxvalues[ index ] );
},
boxValue( index ) {
return this.boxvalues[ index ];
}
},
})
HTML
<div id="app">
<mybox v-for="(value, index ) in boxvalues"
:value="boxValue( index )"
#input="boxValueChanged( index )"
:key="index"
:id="index"/>
</div>
You're right on track, the culprit is the loss of reactivity in this line:
this.boxvalues[index] = !this.boxvalues[ index ];
From the docs:
Vue cannot detect the following changes to an array:
When you directly set an item with the index, e.g.
vm.items[indexOfItem] = newValue
When you modify the length of the
array, e.g. vm.items.length = newLength
There is a simple solution provided by Vue for this use cases: Vue.set() (or this.$set()) method:
this.$set(this.boxvalues, index, !this.boxvalues[index]);
You can read more on this subject here
To add to what Igor said, you can also rewrite the whole array to trigger the reactivity.
ex:
boxValueChanged( index ) {
const boxvalues = [...this.boxvalues]
boxvalues[index] = !boxvalues[index]
this.boxvalues = boxvalues
},

Reset select values in v-autocomplete, in order to add multiple items

I'm creating an application that has a selection box to choose between some template data. However, the user should be able to select the same template option several times and, each time he selects the template, a new informational box appears in the screen.
My problem is that the v-autocomplete component doesn't enable this kind of behavior: we can select one option (or multiple options), but not the same option twice.
I thought about making something like this: every time the user selects the option A, the infobox would appear below and the component would reset to a empty option. Then, the user could choose option A again and, when he chooses it, another info box would appear, how many times the user needs it.
How could I do something like this using vue? I didn't found any component that would do something like this on default, so I think I'll have to tweak the component behavior, but I don't know exactly where to start.
My template:
<template>
<div class="select-wrapper" id="selectBox">
<v-autocomplete
class="select-input"
:items="items"
:name="label"
placeholder="select item"
solo
:value="value"
#change="$event => onChange($event, items)"
item-text="name"
item-value="value"
:required="required"
:rules="[
value =>
!required ||
!!value ||
"required"
]"
></v-autocomplete>
</div>
</template>
And my Vue code:
<script lang="ts">
import { defineComponent } from "#vue/composition-api";
import Vue from "vue";
interface SelectItem {
name: string,
value: string
}
interface SelectBoxProps {
items: SelectItem[];
value: string;
onSelect: ({ target }: { target?: SelectItem }) => void;
hasResetSelection: boolean;
}
export default defineComponent({
name: "SelectBox",
props: {
label: String,
items: Array,
value: [String, Number],
onSelect: Function,
disabled: Boolean,
required: {
type: Boolean,
default: false
},
hasError: Boolean,
errorMessage: String,
hasResetSelection: {
type: Boolean,
default: false
}
},
directives: {
ClickOutside
},
setup({ onSelect, hasResetSelection }: SelectBoxProps) {
const onChange = (selectedValue: string, itemsArr: SelectItem[]) => {
const targetItem = itemsArr.find(i => i.value === selectedValue);
if (hasResetSelection) {
Vue.nextTick(() => {
console.log("onselect should reset value");
return onSelect({ target: { name: "", value: "" } });
});
}
return onSelect({ target: targetItem });
};
return {
onChange
};
}
});
</script>
This was my last attempt with Vue.nextTick, I already tried to tweak the component with ref() and it didn't work as well. Do you have any suggestions?
You can use another variable just to hold the input for the autocomplete component Like this:
var app = new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
items: [{ name : 'hello', value : 1 }, { name : 'world', value : 2 }],
value : null,
values : []
},
methods: {
onChange() {
this.values.push(this.value)
this.$nextTick(() => {
this.value = null
})
},
}
})
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-container>
Values : {{values}}
<v-autocomplete
:items="items"
placeholder="select item"
solo
v-model="value"
item-text="name"
item-value="value"
#change="onChange"
/>
</v-container>
</v-app>
</div>

Vuejs : how to dynamically update value of variable

im newbie here, I want to update the day variable value, this will be implemented in the vuejs-datepicker, it looks like the image below :
This is my code :
data() {
var day = null
var state = {
disabledDates: {
days: [day], // 0,1 (value of the day)
}
}
return {
state: state,
day: day,
}
},
watch: {
'day': function(day){
console.log('day: '+day)
return this.day
},
},
This is my expected image, after the value of the day is 0,1 :
Thanks..
Sounds like you want to control the days passed into the date-picker disabledDates.
For this, I would use an array of days (0-6) and create a computed property for the date-picker config
export default {
data: () => ({ days: [0, 1] }), // or whatever makes sense as a default value
computed: {
state: ({ days }) => ({
disabledDates: { days }
})
}
}
You can control the days property however you want. For example, using checkboxes
<label v-for="(day, index) in ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']" :key="index">
{{ day }}
<input type="checkbox" v-model="days" :value="index">
</label>

Vue Component does not render changes of object (despite $set being used)

I am trying to build a Vue component that displays the hour and minute of a Date and emits a changed version when a + or - button is pressed.
Screenshot: https://i.imgur.com/hPUdrca.png
(not enough reputation to post image)
Using the Vue.js Devtools (in Google Chrome) I observed that:
The change event fires and contains a correct date
The date prop was updated correctly
It just does not rerender the date.
https://jsfiddle.net/JoshuaKo/6c73b2gt/2
<body>
<div id="app">
<time-input :date="meeting.startDate"
#change="$set(meeting, 'startDate', $event)"
></time-input>
<p>
{{meeting.startDate.toLocaleString()}}
</p>
</div>
</body>
Vue.component('time-input', {
props: {
date: Date,
minuteSteps: {
type: Number,
default: 1
}
},
methods: {
increaseTime: function() {
if (!this.date) return
const newDate = this.date
newDate.setMinutes(this.date.getMinutes() + this.minuteSteps)
this.$emit('change', newDate)
},
decreaseTime: function() {
if (!this.date) return
const newDate = this.date
newDate.setMinutes(this.date.getMinutes() - this.minuteSteps)
this.$emit('change', newDate)
},
time: function() {
if (!this.date) return '??:??'
const h = this.date.getHours().toString()
const m = this.date.getMinutes().toString()
return _.padStart(h, 2, '0') + ':' + _.padStart(m, 2, '0')
}
},
computed: {
},
template: `
<div class="time">
<button :disabled="!date" class="control" #click="decreaseTime">-</button>
<span>{{time()}}</span>
<button :disabled="!date" class="control" #click="increaseTime">+</button>
</div>
`.trim()
})
const app = new Vue({
el: '#app',
data: {
meeting: {
name: 'test meeting',
startDate: new Date(),
endDate: null
}
}
})
The object in meeting.startDate is always the same, so it doesn't trigger anything.
You should create a new Date object each time, so change the lines:
const newDate = this.date
to:
const newDate = new Date(this.date.getTime())
Also, the $set (alias of Vue.set) is intended to add properties that must be reactive. As no propperty is added (just modified), you don't need it here.

Vuetify v-text-field change value

how can i manipulate input value.
Show hier is example
`https://jsfiddle.net/mbqjp4ax/`
if number greater than 5, number 9 should be entered.
if I enter more than 5 it works fine but if I keep typing it will not work as expected.
You dont need to use getElementsByTagName and such things in vue. And $refs have a limited usage too. You should just use v-model.
Here your fiddle fixed
https://jsfiddle.net/pm9zwesr/
<v-text-field
label="Price"
v-model="price"
#input="up">
</v-text-field>
new Vue({
el: '#app',
data () {
return {
price: 123.45
}
},
methods: {
up (){
if (parseFloat(this.price) > 5) {
this.$nextTick(() => {
this.price = 9
})
}
},
reset () {
this.price = 0
}
}
})