Vuejs update a value used with v-for dynamically - vue.js

So I'm making an attendance tracker with Vuejs and Vuetify, and I want it to look like this:
A Calender made up of v-card components, and a list of absences read in from a database. I have my API set up and am able to retrieve a list of absences without any issues, but when it comes to putting them on the screen I have some issues. What I want to do is this:
The user selects the month and year. Each card then shows one day of this month. I have a function called getAbsDate(date) that returns a list of absences for the date passed to it. I want it to work something like this in each card:
<v-card min-height="170" tile>
<v-card-text class="text-center black--text">
{{i}}
<v-sheet
color="blue"
class="pa-1"
v-for="abs in getAbsDate(i+'.'+monthsNums[selMonth]+'.'+selYear)"
:key="abs['id']"
>{{abs["name"]}}</v-sheet>
</v-card-text>
</v-card>
selMonth is the month the user selected, and selYear is the year the user selected. This doesn't work however. I don't get any errors, the cards are just empty. getAbsDate() returns a list of objects. Any ideas as to why this doesn't work?
Thanks!
EDIT
Here is the declaration of my getAbsDate() function.
getAbsDate: function(date) {
let l = [];
this.absences.forEach(abs => {
if (abs["start"] == date) {
l.push(abs);
}
if (abs["end"] == date) {
l.push(abs);
}
let day_start = moment(abs["start"].replace(".", "/"), "DD/MM/YYYY")
.toDate()
.getTime();
let day_end = moment(abs["end"].replace(".", "/"), "DD/MM/YYYY")
.toDate()
.getTime();
let day_date = moment(date.replace(".", "/"), "DD/MM/YYYY")
.toDate()
.getTime();
if (day_start <= day_date && day_date <= day_end) {
l.push(abs);
}
});
return l;
}
}
The formatting is not quite right at the .toDate() and the .getTime(), but in my file it is, s it is not the issue.

Related

v-calendar how to set the default month?

I'm using v-calendar, I want to pass the default date to url and use it to set as the default date of the calendar.
The problem I faced with, is that v-calendar always shows the current date by default.
For example today is 30-01-2023 but I want to show the Feb of 2021.
I pass the default date in url query params.
My current code is like this:
<v-calendar
class="custom-calendar max-w-full"
:masks="masks"
:attributes="filteredEvents"
disable-page-swipe
is-expanded
:from-page="new Date(props.occurrence + '-01T:00:00')"
v-bind="{
fromDate: $props.occurrence ? new Date(occurrence+'01T00:00') : null,
}"
v-model="selectedDate"
#update:from-page="navigationHandler($event)"
>
<template v-slot:day-content="{ day, attributes }">
<CalendarDay :day="day" :attributes="attributes" />
</template>
</v-calendar>
If my props.occurrence = '2022-12, still the $event.year and month returns the current year and month.

Does Vuejs have the ability to combine data fields into one?

I currently have a datetime field in my vue application. I want to split it up, but that would mean having to split it up in my database as well, which I am not interested in. I still want to keep the datetime column in my database table.
So my idea was to make it like 3 seperate fields: datetime, date and time. When a user has entered a date and time, these can be merged into the datetime field.
In Python you would do something like: datetime.datetime.combine( date, time )
Is there are similar method in Vue, or is there a better way of getting around this?
<b-form-row>
<b-col lg="6">
<b-form-group :label="$t('check in time')">
<time-picker v-model="guest.checkInDateTime" />
</b-form-group>
</b-col>
</b-form-row>
<b-form-row>
<b-col lg="6">
<b-form-group :label="$t('check in date')">
<date-picker v-model="guest.checkInDateTime" />
</b-form-group>
</b-col>
</b-form-row>
<b-form-row>
<b-col lg="6">
<b-form-group :label="$t('check in time and date')">
<date-time-picker v-model="guest.checkInDateTime"
:format="format"
:show-second="false"
type="datetime"/>
</b-form-group>
</b-col>
</b-form-row>
Working with dates in Javascript can be nuanced. In Javascript, assuming you have both a date value and a time value, you can easily combine these into a date string used by an html date picker like this:
const date = '2022-08-10' // string returned from date input
const time = '15:00:00' // string returned form time input
const checkInDateTime = date + 'T' + time // ISO String
If you're starting with a Date and you want to break it into a date value and a time value, it's almost easier using string manipulations than working with the Date obj, unless you're using a helper library like dayjs.
Examples:
// Assuming we have a date in ISO String format YYYY-MM-DDTHH:mm:ss
const dateFromString = dateValueFromDB.split('T')[0]
const timeFromString = dateValueFromDB.split('T')[1]
// using Date obj
const d = new Date(dateValueFromDB);
const dateFromObj = `${d.getFullYear()}-${('' + (d.getMonth() + 1)).padStart(2, '0')}-${('' + date.getDate()).padStart(2, '0')}`
const timeFromObj = `${d.getHours()}:${('' + d.getMinutes()).padStart(2,'0')}:${('' + d.getSeconds()).padStart(2,'0')}`
// using dayjs library
const dateFromDayjs = dayjs(dateValueFromDB).format('YYYY-MM-DD')
const timeFromDayjs = dayjs(dateValueFromDB).format('HH:mm:ss')
Now to answer your original question. Once we know how we're getting the correct values, in Vue.js, we can easily get and set these date values using a computed property and a custom setter.
<script>
export default {
data() {
return {
guest: {
checkInDateTime: '2022-09-10 15:00:00' // timestamp returned from database
}
}
},
computed: {
time: {
get() {
return dayjs( this.guest.checkInDateTime ).format('HH:mm:ss')
},
set(val) {
this.guest.checkInDateTime = this.date + 'T' + val
}
},
date: {
get() {
return dayjs(this.guest.checkInDateTime).format('YYYY-MM-DD')
},
set(val) {
this.guest.checkInDateTime = val + 'T' + this.time
}
}
}
}
</script>
Here's the html:
<template>
<div class="datetime-pickers">
<p>date: <input type="date" v-model="date" /></p>
<p>time: <input type="time" v-model="time" /></p>
<p>checkInDateTime: <input type="datetime-local" v-model="guest.checkInDateTime" /></p>
</div>
</template>
When any of the three values are set, the other two are updated accordingly. Here's a CodePen showing this in action:
https://codepen.io/ryanhightower/pen/ExLPobY?editors=1010

Filtering Data Table in PrimeNG

How can I get the number of rows after filtering using PrimeNG's default filters in data table.
[totalRecords]="totalRecords" always shows the records count which is fetched initially.
Even though after filtering, totalRecords value remains same and does not change after filtering.
Example:
initially totalRecords is 50 and after filtering, no.of records it shows in data table is 15. But I cannot get the value 15, instead getting 50.
Is there any way ?
Supposing you have a reference to your datatable component, just ask totalRecords property on it :
<p-dataTable [value]="cars" [rows]="10" [paginator]="true" [globalFilter]="gb" #dt>
...
</p-dataTable>
{{ dt.totalRecords }} records
Demo
The above answer is correct and I'm adding up a little thing to it.
If you want to bind the totalRecords value to your typescript .ts file, then use an (onFilter) event and trigger a function with parameters as $event and dt.totalRecords
In my case, i have given
<p-table #dt [value]="personListData" [columns]="columns" (onPage)="onPageChange($event)" [resizableColumns]="true" [paginator]="true" [rows]="rowsCount" selectionMode="multiple" [(selection)]="selected_data" [loading]="loading" [totalRecords]="totalRecords" class="table table-hover table-responsive table-bordered" [responsive]="true" (onFilter)="handleFilter($event,dt.totalRecords)">
In short,
(onFilter)="handleFilter($event,dt.totalRecords)"
Function in .ts file ,
handleFilter(e,filteredRecordCount){
console.log("filteredRecordCount");
}
NOTE: If you want to use the filtered records count value, then you
can assign it to any variable and use anywhere in your typescript
file.
I'm on Angular 8, and my table is not paginated. dt.totalRecords is always the full amount. So if I have 20 rows, and I get it filtered down to 2 on-screen, dt.totalRecords still = 20.
What I ended up doing was using the onFilter, passing in the entire dt, then using dt.filteredValue:
onFilter(event: any, table: any): void {
if(!!table.filteredValue) {
this.visibleRows$.next(table.filteredValue.length);
}
}
You have to check for null, because if you change the filter but don't filter out any additional rows, filteredValue is null.
html:
<p-dataTable #dt (onFilter)="handleFilter()" [value]="cars" [rows]="10" [paginator]="true" >
...
</p-dataTable>
{{ dt.totalRecords }} records
ts:
#ViewChild('dt', { static: true }) dt: Table;
handleFilter() {
if (this.dt.filteredValue != null)
this.dt.totalRecords = this.dt.filteredValue.length;
else
this.dt.totalRecords = this.cars.length;
}

Date comparision on cshtml view

I am using the below code to compare 2 dates on cshtml view with knockout binding.
data-bind="visible: (new Date(appointmentDate) - new Date() < 0) && isStart()"
It is working fine but that is including time as well while comparing. I don't want to include time in comparision only date.
I quick search on google pointed me to Formatting Date in Knockout Template this will allow us to get the date and compare it. Looking like
data-bind="visible: (
moment(new Date(appointmentDate)).format('MM/DD/YYYY') -
moment(new Date()) < 0) && isStart()"
I didn't try just let me know if works
Also momento allows you to calculate difference of dates
var dateB = moment('2014-11-11');
var dateC = moment('2014-10-11');
console.log('Difference is ', dateB.diff(dateC), 'milliseconds');
console.log('Difference is ', dateB.diff(dateC, 'days'), 'days');
console.log('Difference is ', dateB.diff(dateC, 'months'), 'months');
So basically we would do
data-bind="visible: (
moment(new Date(appointmentDate)).format('MM/DD/YYYY').diff(new Date().format('MM/DD/YYYY'),'days') < 0) && isStart()"

Bootstrap DatePicker Splitting Date

I'm in the process of updating an old booking systems views and I am presently stuck on a solution for updating the calendar widget. As the site is responsive I have opted for the bootstrap datepicker supplied by eternicode https://github.com/eternicode/bootstrap-datepicker.
OK here the issue. I have an old Datepicker that splits the checkin & checkout dates into 3 parts and then formats the date for PHP (n = Month no leading zero)) (j = Day no leading zero) & (Y = Year 4 digit numeric).
// Initiate Params
$checkInDate = mktime(0,0,0,date("n"),date("j") + 1,date("Y"));
$checkOutDate = mktime(0,0,0,date("n"),date("j") + 3,date("Y"));
//CheckInDate
if (!isset($daysI)){
$daysI = date("j",$checkInDate);
}
if (!isset($monthsI)){
$monthsI = date("n",$checkInDate);
}
if (!isset($yearI)){
$yearI = date("Y",$checkInDate);
}
//CheckOutDate
if (!isset($daysS)){
$daysS = date("j",$checkOutDate);
}
if (!isset($monthsS)){
$monthsS = date("n",$checkOutDate);
}
if (!isset($yearS)){
$yearS = date("Y",$checkOutDate);
}
The input boxes markup is as below.
<input type='text' id='fulldate' name='fulldate'>
<label>Enter Day of Arrival (in the format DD) </label>
<input type="text" name="daysI" id="daysI" size="6" maxlength="6" />
<label>Enter Month of Arrival (in the format MM) </label>
<input type="text" name="monthsI" id="monthsI" size="6" maxlength="6" />
<label>Enter Year of Arrival (in the format YYYY) </label>
<input type="text" name="yearI" id="yearI" size="6" maxlength="6" />
Here's where I'm having the problem. The following function works with jQuery UI:
$('#fulldate').datepicker({
showAnim: 'fadeIn',
dateFormat: 'd/m/yy',
onSelect: function(dateText, inst) {
var pieces = dateText.split('/');
$('#daysI').val(pieces[0]);
$('#daysI').val(pieces[1]);
$('#daysI').val(pieces[2]);
}
});
However I cannot get a similar solution to work with the bootstrap-datepicker which I am using as a replacement for jQuery UI ie:
$('#fulldate').datepicker({
format: "d/m/yyyy",
todayBtn: "linked",
todayHighlight: true
onSelect: function(dateText, inst) {
var pieces = dateText.split('/');
$('#daysI').val(pieces[0]);
$('#monthsI').val(pieces[1]);
$('#yearI').val(pieces[2]);
}
});
Thank in advance for any solution..
The documentation gives an example of how to capture the date changed event: bootstrap-datepicker Docs - Change Date Event
Something like this should be in the right direction (untested):
$('#fulldate').datepicker()
.on('changeDate', function(ev){
var newDate = new Date(ev.date);
$('#daysI').val(newDate.getDate());
$('#monthsI').val(newDate.getMonth());
$('#yearI').val(newDate.getFullYear());
});