How to use two arrays in Vuetifyes v-autocomplete - vue.js

I have two arrays, one with 7 boolean values representing the weekdays, and the other with the weekdays names and the value of which day of the week it represents, kind of index of weekdays (0 beeing sunday, and 6 beeing saturday)
This sample is from the ts file belonging to the vue file where the autocomplete is.
export const scheduleDays: TextValueViewModel[] = [
{ Text: "Mon", Value: 1},
{ Text: "Tue", Value: 2 },
{ Text: "Wed", Value: 3 },
{ Text: "Thu", Value: 4 },
{ Text: "Fri", Value: 5 },
{ Text: "Sat", Value: 6 },
{ Text: "Sun", Value: 0 }
];
This is from a view model I have containing this array with booleans representing the weekdays.
public readonly SelectedDays: boolean[] = [false,false,false,false,false,false,false];
I then have a autocomplete where I want to save the clicked checkboxes and that would be saved into the boolean array
<v-autocomplete
v-model="editedReleaseSchedule.ScheduleInterval.SelectedDays"
:items="scheduleDays"
:item-text="item => `${item.Text}`"
:item-value="item => `${item.Value}`"
:label="'ADMINISTRATION_RELEASE_SCHEDULE_DETAILS_SCHEDULED_DAYS' | translate('Selected days')"
:disabled="formDisabled"
:rules="[rules.required]"
outlined
hide-details
multiple
dense
/>
How can I make the clicked value of the weekday array beeing saved into the boolean array in the right index spot? And at the same time I want the correct checkboxes be checked in the autocomplete field.
The implemented auto complete in the interface
Using Vue 2 at my workplace, so no solution for vue 3 would work out for me.
I've tried to google if I can get the index of the v-autocomplete row and use that in item-value like:
editedReleaseSchedule.ScheduleInterval.SelectedDays[index]
but that does not seem possible. I've also tried different ways of filtering before using v-autocomplete, but I still want the whole list, not only the clicked (marked) once.

Use an intermediate model for the selectedValues, watch it, and map the selected values ([1,2,3...,0]) into the real model.
data: () => ({
selectedValues: [],
// ...
<v-autocomplete
v-model="selectedValues"
<!-- etc -->
watch: {
selectedValues(newValues) {
const allFalse = [false,false,false,false,false,false,false];
this.editedReleaseSchedule.ScheduleInterval.SelectedDays = allFalse;
newValues.forEach(value => {
// presumes sunday is the last index, the others are offset by +1
let j = value === 0 ? 6 : value-1;
this.editedReleaseSchedule.ScheduleInterval.SelectedDays[j] = true;
})
},

Related

In vue, how do I filter a data object to only show values from the last 24 hours?

I have an array with some data objects that were created on various dates. I would like to only display the objects that were created within the last 24 hours.
I have tried to use moment for this, by using subtract on the date values, but it has no effect. Maybe someone here could come up with a suggestion.
Here are my computed properties. I use these because I am outputting the data in a bootstrap table, so the "key" represents the different values inside the object.
My table:
<b-card class="mt-4 mb-4">
<b-table
:items="tasks"
:fields="fields"
sort-desc
/>
</b-card>
My array (I am actually importing from a database, but for this question I will just write it manually) Please note I am just showing a single object here. In reality I have hundreds of objects
data: {
tasks: [
{ message: 'Foo' },
{ creationDateTime: '03-02-2022' },
{ isRead: false }
]
}
In my computed properties I then pass them to the table
computed: {
fields() {
return [
key: 'message',
label: 'message'),
sortable: true,
},
{
key: 'creationDateTime',
label: 'Date created',
formatter: date => moment(date).subtract(24, 'hours').locale(this.$i18n.locale).format('L'),
sortable: true,
},
{
key: 'isRead',
label: 'Has been read'),
sortable: true,
}
]
},
},
As I said, using subtract does not work. It still shows all objects in my database
I tried doing the reduction on the whole array as well, but I just get the error:
"TypeError: this.list.filter is not a function"
newTasks(){
if(this.tasks){
return moment(this.tasks.filter(task => !task.done)).subtract(24, 'hours')
}
}
I'm out of ideas.
In Moment, you can check if a date is within the last 24 hours with:
moment().diff(yourDate, 'hours') < 24
(note that future dates will also pass this check, but you can easily adjust it).
You can put this into your computed property:
newTasks(){
if(!this.tasks){
return []
}
return this.tasks.filter(task => !task.done && moment().diff(task.creationDateTime, 'hours') < 24)
}
And that's it, now newTasks should contain all tasks from the last 24 hours that are not done.

How to sort computed values in a v-data-table

I have a v-data-table from Vuetify in my Vue.js app.
The table has a column of computed values.
I wanna make that column sortable.
What do I have to do?
What I tried:
I was looking into the sort function of the v-data-table-header.
It offers: sort?: (a: any, b: any) => number.
However, when I define that function for my column the values in the column are still not sorted.
HTML:
<v-data-table
:headers='headers'
:items='items'
>
<template v-slot:item.complete='{ item }'>
<span v-if='!isComplete(item)' class='error--text'>not complete</span>
<span v-else>complete</span>
</template>
</v-data-table>
Script:
readonly headers: DataTableHeader[] = [
{
text: 'Completeness',
value: 'complete',
sort: (a, b) => {
console.log(a, b);
return 1;
}
},
];
items = [
{
name: "foo",
tasks: 3
},
{
name: "bar",
tasks: 42
}
]
isComplete(item: any): boolean {
return 12 <= item.tasks && item.tasks <= 50;
}
The order doesn't change when I enable sorting and the log says:
undefined undefined
undefined undefined
undefined undefined
...
What do I need to do to sort computed values?
I don't think you can sort computed data in a table unless the objects inside items array each have a field called complete with some value, because that's what the table is looking for to get the value (hence undefined).

How to show icon next to value in cloumn in aurelia slickgrid/slickgrid?

I want to show en edit icon next to value in Amount column. This is because the Amount column is actually editable.But to give that as a hint to user, i want to show some edit icon next to it. How to do that in aurelia slickgrid?
Or maybe there is a way to highlight a field on hover ?
I am using aurelia slickgrid and looking if there is some option in aurelia slickgrid itself.
Go to the aurelia slickgrid example link and click on the link of example's source code
When you open it, there is a method called defineGrids
/* Define grid Options and Columns */
defineGrids() {
this.columnDefinitions1 = [
...,
...,
...,
...,
...,
{ id: 'effort-driven', name: 'Effort Driven', field: 'effortDriven', formatter: myCustomCheckmarkFormatter, type: FieldType.number, sortable: true, minWidth: 100 }
];
... rest of the code
}
The row with id effort-driven is where the icons are placed. On the other words, when you push a data collection(usually array of json object) to the table, values of the data objects with key name effort-driven are given to column with id effort-driven. Furthermore, for each passed value to the column, the method myCustomCheckmarkFormatter reformat it(for example 0 -> false or null -> not filled) and place it to the corresponding table's cell. look at the below method:
// create my custom Formatter with the Formatter type
const myCustomCheckmarkFormatter: Formatter<DataItem> = (_row, _cell, value) => {
// you can return a string of a object (of type FormatterResultObject), the 2 types are shown below
return value ? `<i class="fa fa-fire red" aria-hidden="true"></i>` : { text: '<i class="fa fa-snowflake-o" aria-hidden="true"></i>', addClasses: 'lightblue', toolTip: 'Freezing' };
};
As you can see, when the method is called, it returns an icon such as <i class="fa fa-fire red" aria-hidden="true"></i> which is placed in the table's cell.
I added an edit icon next to Amount,
{
id: "Edit",
field: "edit",
excludeFromColumnPicker: true,
excludeFromExport: true,
excludeFromQuery: true,
excludeFromGridMenu: true,
excludeFromHeaderMenu: true,
minWidth: 30,
maxWidth: 30,
formatter: Formatters.editIcon,
},
and used this custom format from ghiscoding comment:
const customEditableInputFormatter: Formatter = (_row, _cell, value, columnDef, dataContext, grid) => {
const isEditable = !!columnDef.editor;
value = (value === null || value === undefined) ? '' : value;
return isEditable ? `<div style="background-color: aliceblue">${value}</div>` : value;
};
The result is as shown in the picture.

How to use $t from vue-i18n inside Vuex store to initialize static strings

In my vuex store module I have provinceData to supply as datasource for Vuetify dropdown selection box.
provinceData: [
{value:"AB", text: "Alberta"},
{value:"BC", text: "British Columbia"},
...
],
I can import i18n from '../plugins/i18n' and confirm in console output that i18n.t('province.BC') return me proper text from resource files
i18n.t('province.BC') British Columbia
click onLanguageChange fr
i18n.t('province.BC') British Columbia (Fr)
But how I can insert these translations into datasource?
provinceData: [
{value:"AB", text: ???i18n.t('province.AB')??? },
{value:"BC", text: ???i18n.t('province.BC')??? },
...
]
Now I realized what mistake I did by wrapping i18n.t('province.AB') into back ticks. Here is corrected version which render english only messages:
provinceData: [
{value:"AB", text: i18n.t('province.AB') },
{value:"BC", text: i18n.t('province.BC') },
...
]
Moreover, will it be reinitialized if I switch the current locale?
PS. When getter for this datasource is hit I can see that message retrieved according to current locale. But dropdown box izn't reloaded. That's the problem
Following getter print correct translation every time it called:
provinceData: (state) => {
console.log("i18n.t('province.BC')",i18n.t('province.BC'));
return state.provinceData;
},
Because the provinceData inside the store it can't be modified by anything but mutators.
So I decided to create this array right in the getter and it turns out to be quite fast.
provinceData: ( state ) =>
{
const provinceData = [ "AB", "BC", "MB", "NB", "NF", "NT", "NS", "NU", "ON", "PE", "QC", "SK", "YT" ];
let provinces = [];
provinceData.forEach( (province) => {
provinces.push
({
value : province,
text : i18n.t( 'province.'+province )
})
})
return provinces;
}

ChartJS Unix Time Values changed

I'm importing data from a Sybase database into ChartJS in VueJs2. I'm using the vue-chart module
I push the timestamps into an array as Unix times using
this.firstIn(new Date(tnaDetails[0].Sunday_FirstIn).getTime())
So:
[Sunday_FirstIn:2010-01-17 08:00:00.0]
Would convert to
1263708000000
Which I then add to the dataset:
datasets: [{
type: 'line',
label: "First In",
backgroundColor: "green",
data: this.firstIn,
fill: false
}
]
However, when the data is plotted on the graph, the values are changed. The above Unit Timestamp becomes
1263700000000
Which obviously returns the wrong time. I'm not doing anything to the ticks in the options.
Below is a result of the numbers being changed. The console has the original data:
Is there a setting that alters the precision/values of numbers in ChartJS that I'm not aware of?
Thanks.
Seth
For anyone who has any similar problem in future, I patched together a few solutions I found.
Firstly, from here Unix Timestamp in JavaScript, I wrote the method:
getTimeString: function(dateString) {
var hours = new Date(dateString).getHours();
var mins = new Date(dateString).getMinutes();
return Math.round((new Date("1970-02-01 " + hours + ":" + mins)).getTime());
}
The important part here is to make sure you have the same day. Not doing this will cause the ChartJS graph to plot the times in different places on the y-axis, even if the hours are the same.
Then from this StackOverFlow question and the related plunker, in the chart options, I have:
{
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
position: 'left',
ticks: {
callback: value => {
let date = moment(value);
if (date.diff(moment('1970-02-01 23:59:59'), 'minutes') === 0) {
return null;
}
return date.format('H:mm');
},
stepSize: 3.6e+6
}
}]
}, //end scales
tooltips: {
callbacks: {
label: function(toolTipItem, data) {
let date = moment(toolTipItem.yLabel);
if (date.diff(moment('1970-02-01 23:59:59'), 'minutes') === 0) {
return null;
}
return date.format('H:mm');
}
}
}
}
Pay attention to the callbacks. They will format the time, calculating the difference from a set time to the time you need plotted. In the first function, you could really use any day, it wouldn't matter, as long as it's the same day. The stepSize will display hourly intervals on the yAxis.