How to display a week range v-date-picker range? - javascript

I am using v-calendar as a date picker in my Vue project. My objective is to select complete week - 7 days fixed from sunday to saturday. I have been looking around in the documentation but unable to get my head around it.
This is what I have as an example
https://codepen.io/achaphiv/pen/OJXjooB
<div id='app'>
<v-date-picker v-model="value" :available-dates="availableDates" is-inline></v-date-picker>
The current date is: {{ value || 'null' }}
</div>
new Vue({
el: '#app',
data() {
const now = new Date()
const later = new Date(now.getTime() + 5 * 60 * 1000)
return {
value: null,
availableDates: [
{ start: now, end: later }
]
}
}
})

If I understood you correctly try like following snippet:
new Vue({
el: '#app',
data() {
return {
value: null,
availableDates: {
start: new Date(),
end: new Date(new Date().setDate(new Date().getDate() + 7))
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/v-calendar#1.0"></script>
<div id='app'>
<v-date-picker v-model="value" :available-dates="availableDates" is-inline></v-date-picker>
The current date is: {{ value || 'null' }}
</div>

Related

How to set max date in a kendodatepicker every time another date is chosed

i have two kendodatepickers "startDate" and "endDate". I want every time the user set a date in startdate, establish the max date one month forward from the selected date to pick in endDate datepicker.
I am setting up the first time in this way:
$("#datStartDate").kendoDatePicker({
start: "month",
depth: "year",
format: "dd/MM/yyyy",
dateInput: true,
change: (e) => {
return moc.rangeStartDate("datStartDate", "datEndDate");
},
min: new Date(1900, 0, 1),
max: new Date(),
value: new Date()
});
$("#datEndDate").kendoDatePicker({
start: "month",
depth: "year",
format: "dd/MM/yyyy",
dateInput: true,
max: new Date(),
change: (e) => {
return moc.rangeEndDate("datStartDate", "datEndDate");
},
value: new Date()
});
I tried this to set the max value, each time the startDate picker is cheanged:
$("#datStartDate").change(() => {
let startDate = ($("#datStartDate").val()).split("/");
console.log("cambio de fecha", parseInt(startDate[2]), parseInt(startDate[1]), parseInt(startDate[0]))
let datePicker = $("#datEndDate").data("kendoDatePicker");
datePicker.max(new Date(parseInt(startDate[2]), parseInt(startDate[1]), parseInt(startDate[0])));
datePicker.value(new Date(parseInt(startDate[2]), parseInt(startDate[1]), parseInt(startDate[0])))
})
It doesnt works and i dont get an error. How can i do this? Thank you so much for you time.
I am using this:
KendoUI
JavaScript
ASP .NET MVC
RAZOR
jquery
you can use it in Jquery
function startChange() {
var endPicker = $("#dtpStartDate").data("kendoDatePicker"),
startDate = this.value();
if (startDate) {
startDate = new Date(startDate);
startDate.setDate(startDate.getDate());
endPicker.max(startDate + 30);
}
}
function endChange() {
var startPicker = $("#dtpEndDate").data("kendoDatePicker"),
endDate = this.value();
if (endDate) {
endDate = new Date(endDate);
endDate.setDate(endDate.getDate());
startPicker.max(endDate - 30);
}
}
and in razor files you can create datepickers like this
<div class="form-group">
<label class="col-md-4 control-label">#Html.LabelFor(m => m.StartDate)</label>
<div class="col-md-8">
#(Html.Kendo().DatePickerFor(m => m.StartDate)
.HtmlAttributes(new { #Id = "dtpStartDate", style = "width:100%", required = "required", validationMessage = "Select Start Date" })
.Events(e => e.Change("startChange")))
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">#Html.LabelFor(m => m.EndDate)</label>
<div class="col-md-8">
#(Html.Kendo().DatePickerFor(m => m.EndDate)
.HtmlAttributes(new { #Id = "dtpEndDate", style = "width:100%", required = "required", validationMessage = "Select End Date" })
.Events(e=>e.Change("endChange")))
</div>
</div>

Vue dynamic calculation on input change

I want to calculate the earnings from share using vue. I'm subtracting the day closing amount to the start one. I'm not able to display the result on the Dom.
JSfiddle: https://jsfiddle.net/4bep87sf/
This is the code:
let app = new Vue({
el: '#app',
data: {
s: '',
e: '',
tot: '0'
},
watch: {
e: function(){
this.tot = (this.e + this.s);
return this.f;
}
});
Use a computed property:
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
data: () => ({
s: 0,
e: 0
}),
computed: {
tot() {
return Number(this.s) + Number(this.e);
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model="s" type="number">
<input v-model="e" type="number">
<pre>{{s}} + {{e}} = {{tot}}</pre>
</div>
Also note you need to cast your values as Number() if you want the sum to be correct. If they're interpreted as strings a + b = ab.
Very close to tao answer. Only "fix" two User experience issues (Not directly related to Vue).
Issue 1: "030" or "30" ahhhh:
First, if you set a default value (0 for example), when the user focuses input and type "3" the output is 03! (or 30) ==> Very annoying (Especially on mobile).
Sometimes it's better to set the input value to null and show input placeholder (Fix this annoying issue).
Issue 2 (No meaning result):
The output 0 + 0 = 0 does not contribute too much to the user. Sometimes it's better to put the sum inside v-if.
<p v-if="number1 && number2">{{total}}</p>
Basic code example
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
data: () => ({
number1: {
type: Number,
value: null,
placeholder: "Enter number 1",
},
number2: {
type: Number,
value: null,
placeholder: "Enter number 2",
}
}),
computed: {
total() {
return Number(this.number1.value) + Number(this.number2.value);
}
},
})
span{
color: red;
font-weight: bold
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h3></h3>
<div>
<label>Number 1:</label>
<input autofocus v-model="number1.value" type="number" v-bind:placeholder="number1.placeholder">
</div>
<div>
<label>Number 2:</label>
<input v-model="number2.value" type="number" v-bind:placeholder="number2.placeholder">
</div>
<p>Total:<span v-if="number1.value && number2.value"> {{total}}</span></p>
</div>
v-model.lazy also sometimes useful for calucations:
By default, v-model syncs the input with the data after each input
event (with the exception of IME composition, as stated above). You
can add the lazy modifier to instead sync after change events. https://v2.vuejs.org/v2/guide/forms.html#lazy

VueJS reactive Date object

Rather beginner question, but I couldn't find a solution anywhere.
I have 2 buttons that increment/decrement a given Date object by +/- 1 day. The object is updated, but the changes are not displayed. I found out it's because the Date Obj is not reactive, but I didn't find a solution or a workaround to this.
JSFiddle Demo
HTML:
<div id="app">
<button #click="inc">+ 1 day</button>
<button #click="dec">- 1 day</button>
<br /><br />
{{date}}
</div>
JS/Vue:
new Vue({
el: "#app",
data: {
date: new Date()
},
methods: {
inc () {
this.date.setDate(this.date.getDate() + 1)
console.log(this.date)
},
dec () {
this.date.setDate(this.date.getDate() - 1)
console.log(this.date)
}
}
})
In the console the Date is incresed/decreased fine, but the date rendered on the page just stays the same. Can anybody help with this? Thanks.
You are modifying the date object in place in which case Vue can not detect the changes, create a new date object instead:
https://jsfiddle.net/13gzu8xs/1/
new Vue({
el: "#app",
data: {
date: new Date()
},
methods: {
inc () {
this.date.setDate(this.date.getDate() + 1)
this.date = new Date(this.date) // create a new date and assign to this.date
},
dec () {
this.date.setDate(this.date.getDate() - 1)
this.date = new Date(this.date)
}
}
})

bootstrap-datepicker bound to vue v-model reverts to previous data when losing focus

I have a form where a datepicker follows a text input. After the text input has been given, the datepicker receives a date from an ajax call. The focus is now on the datepicker, which shows (as expected) the received date. When the user tabs to the next input, the datepicker reverts to its previous data, which ends up being the placeholder in most cases.
The vue app code:
var app = new Vue({
el: "#app",
data: {
theDate: '',
aNumber: 0,
bNumber: 0
},
mounted() {
$("#aDate").datepicker({
format: 'dd/mm/yyyy'
});
$("#aDate").datepicker().on(
"changeDate", () => {
this.theDate = $('#aDate').val()
}
);
},
methods: {
check() {
console.log('theDate: ' + this.theDate + ', aNumber: ' + this.aNumber + ', bNumber: ' + this.bNumber);
},
setDate() {
this.theDate = '18/12/2018';
}
}
})
And the html:
<body>
<div id="app">
<input type="text" id="bNumber" v-model="bNumber" /><br>
<input type="text" id="aDate" placeholder="mm/dd/yyyy" v-model="theDate" /><br>
<input type="text" id="aNumber" v-model="aNumber" /><br>
<button type="button" #click="check">Check</button>
<button type="button" #click="setDate">Set Date</button>
</div>
</body>
This can be observed in this fiddle if following these steps
Enter any number in the top input
Then tab to the datepicker input
Click the "Set Date" button (simulating received data)
Then focus on the datepicker input again by clicking in it
Now tab out to the next input
The date in the datepicker has reverted to the previous value
How can this be prevented and the data be made persistent?
I have tried the solution from this question but the behaviour is the same.
The problem is the actual date value being controlled by the datepicker, in which case there's no point in using v-model. So much that setting the theDate to any value does not really affect anything. This is understandable since you are using Bootstrap which has a jQuery dependency. I would recommend Vue-flatpickr as an alternative. But if you need to stick with this, here's a possible fix:
I've removed unnecessary attributes for brevity:
<input type="text" ref="datepicker" placeholder="mm/dd/yyyy" />
var app = new Vue({
el: "#app",
data: {
theDate: '',
aNumber: 0,
bNumber: 0
},
mounted() {
$(this.$refs.datepicker).datepicker({
format: 'dd/mm/yyyy'
})
.on("changeDate", e => {
this.update(e.target.value);
});
},
methods: {
check() {
console.log('theDate: ' + this.theDate + ', aNumber: ' + this.aNumber + ', bNumber: ' + this.bNumber);
},
setDate() {
this.update('18/12/2018');
},
update(value) {
$(this.$refs.datepicker).datepicker("update", value);
}
}
})
Basically, you need to update the date with the provided API.

How to format a (possibly null/empty) date in VueJS

Using Vue.JS 1.0, I couldn't find a simple way to properly format a JSON date that can be empty.
I tried with vue-filter npm package date filter but it fails if the date is empty. For example if my data is:
{ name: "John", birthday: null }, /* unknown birthday */
{ name: "Maria", birthday: "2012-04-23T18:25:43.511Z" },
returns
John 12/31/1969 9:00:00 PM <-- null date should be blank
Maria 4/23/2012 3:25:43 PM <-- ok
The code i am using:
<!DOCTYPE html><html>
<head>
<script src="lib/vue/dist/vue.min.js"></script>
<script src="lib/vue-filter/dist/vue-filter.min.js"></script>
</head>
<body>
<div id="app">
<h1>Without Filter:</h1>
<div v-for="person in list">
<div>{{person.name}} {{person.birthday}}</div>
</div>
<h1>With Filter:</h1>
<div v-for="person in list">
<div>{{person.name}} {{person.birthday | date }}</div>
</div>
</div>
<script>
new Vue({
el: "#app",
data: {
list: [
{ name: "John", birthday: null },
{ name: "Maria", birthday: "2012-04-23T18:25:43.511Z" },
]
}
});
</script>
</body>
</html>
What is the proper way to format a date, that will also make show blank if date is null?
Write a custom filter to wrap the date filter. If the input is null, return null, otherwise return Vue.filter('date')(input)
Vue.filter('dateOrNull', function(d, ...others) {
return d ? Vue.filter('date')(d, ...others) : null;
});
new Vue({
el: "#app",
data: {
list: [{
name: "John",
birthday: null
}, {
name: "Maria",
birthday: "2012-04-23T18:25:43.511Z"
}, ]
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<script src="//rawgit.com/wy-ei/vue-filter/master/dist/vue-filter.min.js"></script>
<div id="app">
<h1>Without Filter:</h1>
<div v-for="person in list">
<div>{{person.name}} {{person.birthday}}</div>
</div>
<h1>With Filter:</h1>
<div v-for="person in list">
<div>{{person.name}} {{person.birthday | dateOrNull '%B'}}</div>
</div>
</div>
It doesn't work well:
Roy answers exactly what I asked. But it turned out that vue-filter was not good for my needs. I needed '%c' to show date in browser's locale format (bad idea). vue-filter source was actually doing the following: (rewrited as a stand alone filter, to avoid the dependency):
Vue.filter('date', function (d) {
var date = new Date(d);
return d ? date.toLocaleDateString() + ' ' + date.toLocaleTimeString().trim() : null;
});
It is terrible: each browser works differently. And dates with unknown timezone are assumed UTC and moved to local timezone causing this when living at GMT-3:
New plan:
Use Moment.js with a custom filter:
Vue.filter('moment', function (date) {
var d = moment(date);
if (!d.isValid(date)) return null;
return d.format.apply(d, [].slice.call(arguments, 1));
});
Don't forget <script src='moment.js'>.
Usage: {{ date | moment "dddd, MMMM Do YYYY" }}
See also: Moment Date and Time Format Strings
I also tried vue-moment npm package BUT it depends on CommonJS / require() syntax, and I don't want to use webpack/browserify just for this,

Categories

Resources