Vuejs : how to dynamically update value of variable - vue.js

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>

Related

Show select by value with Vue

i have this select:
<b-form-group
label-cols-sm="2"
label-cols-lg="2"
content-cols-sm
content-cols-lg="10"
v-bind:label="$t('vue.contract_terms')"
label-for="contract_terms"
v-show="contract">
<b-form-select
:options="contract_terms"
v-model="form.contract_data.contract_terms"
id="contract_terms"
:state="validate(form.contract_data.contract_terms)">
</b-form-select>
</b-form-group>
i want to show it when in my other select i choose all values except "vat" and "international_contract"
this is my js (hiring_types are the options of my other select) setSelected is my method to show my select above but i want to show it when i choose all values except "vat" and "international_contract":
data: (instance) => {
return {
contract: true,
}
},
computed:{
hiring_types () {
return [
{value: 'contract' , text: this.$t('vue.freelance')},
{value:'vat' , text: this.$t('vue.employment')},
{value: 'apprenticeship', text: this.$t('vue.apprenticeship')},
{value:'co_co_co' , text: this.$t('vue.co_co_co')},
{value: 'international_contract' , text: this.$t('vue.international_contract')}
]
},
},
methods:{
setSelected(value) {
this.hiring_contract_category = value;
this.contract = value === 'contract';
},
}
How can i do?
You can use Vue's template conditionals:
<template v-if='["vat", "international_contract"].map(val => !hiring_types.map(entry => entry.value).includes(val)).every(v => v)'>
<!-- insert b-form-group -->
</template>
Better to make this conditional a computed property and use it in your template for brevity:
// in your script
{
computed: {
showFormGroup () {
return ["vat", "international_contract"]
.map(val => !hiring_types.map(entry => entry.value)includes(val))
.every(v => v)
}
}
// in your template
<template v-if='showFormGroup'> ... </template>

How to add a Date Selector to Chartjs in the context of Vue.js

I am new to Vuejs, i have implemented chart using Chartjs, i want to add date selector to my chartjs. I have used 4 buttons, so whenever i click any of the button my chart should change accordingly.
Initially i tried implementing each button with each method, but i don't feel that as an effective way to do so.
> Here is my code: https://jsfiddle.net/95kspb70/3/
I want the chart to change when ever i click any of the button that i have used, i mean i have used 4 buttons, suppose say i clicked 3m, my chart should show previous 3months data only.
Please help me with this, I don't know how exactly i should do it in order to solve this.
You need to filter the data based on the date and rerender the chart for the new data.
Here is the working jsfiddle
I add click event #click="selectPeriod" inside html:
<div id='app'>
<div id="range-selector">
<input type="button" id="1m" #click="selectPeriod" class="period ui-button" value="1m" />
<input type="button" id="3m" #click="selectPeriod" class="period ui-button" value="3m" />
<input type="button" id="6m" #click="selectPeriod" class="period ui-button" value="6m" />
<input type="button" id="all" #click="selectPeriod" class="period ui-button" value="All" />
</div>
<canvas ref='chart' width='800' height='600'></canvas>
</div>
and following js code:
new Vue({
data: () => ({
date: [
1567295500.0,
1567893700.0,
1568615220.0,
1569024000.0,
1569888120.0,
1572456400.0,
1572772560.0,
1574809200.0,
1576706160.0,
1577718000.0,
1578610800.0,
1582650220.0,
1583174000.0,
1584063360.0,
1587427200.0,
1587573420.0,
1588637800.0,
1589587420.0,
1589989800.0
],
challenge: [
0.45,
2.12,
2.55,
3.15,
4.16,
5.56,
6.258,
7.256,
8.364,
9.154,
10.245,
11.654,
12.364,
13.785,
14,
15.32,
16.87,
17.852,
18.254,
19
],
data: []
}),
mounted() {
this.data = this.date.map((date, index) => ({
x: new Date(date * 1000),
y: this.challenge[index]
}))
this.buildGraph(this.data);
},
methods: {
buildGraph(data) {
console.log(data.length);
let ctx = this.$refs.chart.getContext('2d')
let chart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
data
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'month',
displayFormats: {
month: 'MMM YYYY'
}
}
}],
yAxes: [{
ticks: {
callback: function(value, index, values) {
return value + 'k';
}
}
}]
}
}
})
},
selectPeriod(event) {
let period = event.target.value;
let minValue = new Date(Math.max(...this.date) * 1000);
let axisXMin = new Date(Math.min(...this.date) * 1000);
switch (period) {
case "1m":
minValue.setMonth(minValue.getMonth() - 1);
break;
case "3m":
minValue.setMonth(minValue.getMonth() - 3);
break;
case "6m":
minValue.setMonth(minValue.getMonth() - 6);
break;
case "1y":
minValue.setYear(minValue.getFullYear() - 1);
break;
default:
minValue = axisXMin;
}
let data = this.data.filter(el => {
return el.x >= minValue
});
this.buildGraph(data);
}
}
}).$mount('#app')

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.

Vue JS date of birth picker

I'm setting up a date of birth field.
How can I set the "Year" as my first popup window? instead of calendar view popup.
The view package I'm using is "vue2-datepicker"
I would like to choose the "YEAR" first and then "Month" and then "Date"
This is what I want to show up first when I click the calendar icon.
At the moment, when I click the calendar icon it show the default calendar.
Here's the code I have at the moment. It's working fine with the default calendar but I just want to default to the year selection first and then Month and then date.
<template>
<div class="styled-form__field">
<label class="styled-form__label">{{ label }}</label>
<span
:class="['styled-form__error', {'is-visible': error}]"
>{{ error }}</span>
<date-picker
:value="value"
lang="en"
:format="'DD MMMM YYYY'"
:placeholder="' '"
:width="'auto'"
:input-class="datePickerClass"
:not-before="datePicker.start"
:not-after="datePicker.finish"
#input="changeHandler"
></date-picker>
</div>
</template>
<script>
import moment from 'moment';
import DatePicker from '../common/DatePicker.vue';
export default {
components: {
DatePicker
},
props: {
value: {
required: true
},
label: String,
error: String
},
data() {
return {
datePicker: {
start: moment().subtract(115, 'years').toDate(),
finish: moment().subtract(1, 'days').toDate()
}
};
},
computed: {
datePickerClass() {
return this.error ? 'styled-form__date-picker is-invalid' : 'styled-form__date-picker';
}
},
methods: {
changeHandler(newValue) {
let parsedValue = '';
if (newValue !== '') {
parsedValue = moment(newValue).format('YYYY-MM-DD');
}
this.$emit('input', parsedValue);
}
}
};
</script>
The standard browser datepicker doesn't let you alter its behaviour like that. You might find another datepicker component that suits you better, but I suspect you will have to write your own, combining separate inputs for year, month and date. The effort will only be worth it if you're super-picky about the result. For most situations, you will be better off with a ready-made component.

How to calculate result from dynamic fields

I am trying to calculate a difference between dynamic fields and then add all of the differences. I am using date fields as I need to record the difference between each group of dates and then result would be total number of years. I am providing an example as below
<div id="app">
<form action="">
<div class="group" v-for="(group,id) in groups" :key="id">
<input type="text" v-model="group.from">
<input type="text" v-model="group.till">
<button #click="removeGroup(id)">Remove</button>
</div>
</form>
<button #click="addGroup">add</button>
<h2>Results</h2>
{{ result }}
<pre>{{ $data }}</pre>
So, the idea is that I should be able to calculate the difference between "from" field and "till" field in the groups array but at the same time result should reflect the sum of all differences. I tried with watch but in actual form there are a lot of fields and I might be over thinking. would appreciate some help. here is the vue code
var vm = new Vue({
data: {
groups: [
{
from: '',
till: ''
}
],
},
computed: {
result() {
return 0
}
},
methods: {
addGroup: function () {
var additional = {
from: '',
till: ''
}
this.groups.push(additional)
},
removeGroup: function (id) {
var index = this.groups[id]
this.groups.splice(index, 1)
},
}
}).$mount('#app')
Just use a computed property. Because of groups reactivity any reference to this.groups would trigger an update:
import moment from 'moment'
...
// assuming your date is a string
computed: {
result() {
return this.groups.reduce((group, total) => {
return total + moment(group.from).diff(group.till, 'years')
}, 0)
}
},
Update
Now that I know you're working with dates, I'd suggest a library like moment or fecha. Here's how to calculate differences with moment