My product table is sorted with initialSort by the product release month ascending. I also grouped my products by a codename which is determinate by the ajax json response url and renamed them to readable names with a groupBy function. Now I want to sort my groups individual without loosing the month sorting in my groups. How is that possible?
var table = new Tabulator("#tableid", {
ajaxURL: url,
layout: "fitColumns",
groupBy: "codename",
groupBy:function(data){
if (data.codename == "X123") {
return "Productname for X123";
}
if (data.codename == "X124") {
return "Productname for X124";
}
…
…
},
initialSort:[
{column:"month", dir:"asc"}
],
columns: [
{ title: "Product", field: "codename"},
{ title: "Month", field: "month"},
…
…
…
]
});
Not exactly sure what you mean by "sort my groups individual", but is this what you're looking for ?
https://jsfiddle.net/r3f7pysw/
initialSort:[
{column:"month", dir:"asc"},
{column:"codename", dir:"asc"}
],
NOTE(1) : I dont think you want to return that string for your grouping, when it seems like its just the header Display string, and you're still going to be sorting on "codename" (becoz the string is the same with a change at the end, which really takes a "little" long to compare each time). But maybe you do...
NOTE(2) : Adding the seconds initialSort is like Ctrl-Click on the sorting to sort by multiple criteria. So if you single click on say, Month, remember that destroys the currentSort array and sets it just to Month.
Related
I have a PrimeVue DataTable (https://primefaces.org/primevue/datatable) that is arranged as such:
<DataTable
:rows = "5"
:value = "apiItems"
>
<Column
v-for="data in columns"
:field="data.field"
:header="data.header"
:key="data.field"
:sortable="true"
/>
</DataTable>
Where the table is being populated by data received from an API call, and the field layout is as listed:
const columns = [
{ field: 'initialDate', header: 'Initial Date'},
{ field: 'finishDate', header: 'Finish Date'}
];
The data being retrieved from the API is in the form of a JS Date() component that is displayed as such: "08/01/2022 08:33:32" for both initialDate and finishDate
How can I the columns via ascending or descending by both the date AND time stamps, whereas now, sorting the columns just rearranges the values based on the first digits available, which happen to be the month; I need them to sort corresponding to not only the correct month, but the time as well.
Any help is appreciated, thanks.
What you are receiving from the API cannot be a Date() object, but is probably a string. And so, if you sort by this column, the rows are sorted lexicographically, but not chronologically.
To avoid that, you should convert the data coming from the API into Date objects. If you convert that to a timestamp, that's very convenient to sort by chronologically:
for (item of apiItems) {
item.initialDateObj = new Date(item.initialDate)
item.initialDateTimestamp = item.intialDateTimeObj.getTime()
}
You can then specify that as the field to sort a column by:
const columns = [
{ field: 'initialDate', sortField: 'initialDateTimestamp', header: 'Initial Date'},
{ field: 'finishDate', sortField: 'finishDateTimestamp', header: 'Finish Date'}
];
how are you? I'm trying to move a filter inside the fetch I'm doing to bring my data from Builder.io and I'm struggling with one of them here. The title search works fine, but the second one don't. My objective is to filter between the entries to catch only the ones that match at least one of the annotationArray items.
The annotationArray can be, for example:
const annotationArray = ['Video', 'Image', 'GPS']
or just
const annotationArray = ['Video']
or whatever.
And the entries have an annotation field that consists in a string where I pass the annotations, like this:
const entries = [{title: 'First', annotation: 'Video, GPS'}, {title: 'Second', annotation: 'GPS'}, {title: 'Third', annotation: 'Video, Image'}]
So, for example, if the annotationArray is ['Video', 'GPS'], I want to fetch all of them. But if it's ['Video'], only the third and first, and so.
Currently I have this code
const sets = await builder.getAll('open-dataset', {
options: { noTargeting: true },
omit: 'data.blocks',
limit: 100,
query: {
data: {
title: { $regex: search, $options: 'i' },
annotation: { $regex: annotationArray && annotationArray.join(' '), $options: 'i' },
}
}
});
The result of annotationArray.join(' ') can be, for example, Video Image GPS or just Image. And annotation Video Image or whatever.
So I need to filter between the entries and fetch only the ones that contain at least one of the annotationArray strings.
My code is failing because currently it only fetches the ones that have all the annotationArray items, and not the ones that have at least one. I don't know how to do it with MondoDB query operators... previously, I had this code with javascript and it worked fine.
const filtered = entries.filter(item => annotationArray.some(data => item.annotation.includes(data)));
can somebody help me? thanks
I am using the CSV package for Node to parse some CSV files in a project. I need to be able to handle cases with and without a header. So either of:
const withHeader = `h1,h2,h3
d1a,d2a,d3a
d1b,d2b,d3b`;
const withoutHeader = `d1a,d2a,d3a
d1b,d2b,d3b`;
The number of columns and their names are unknown to my application. Either they will be read from the header, or they should be numerically generated, e.g. col0,col1,col2.
This is where I run into a problem. I always want the output of csvParse to be in object literal form. This is easy when the end-user has indicated that the CSV has a header:
> csvParse(withHeader, {columns: true})
[
{ h1: 'd1a', 'h2': 'd2a', 'h3': 'd3a' },
{ h1: 'd1b', 'h2': 'd2b', 'h3': 'd3b' }
]
But when the user indicates that there is not a header row, it doesn't seem to be possible to end-up with the data in object literal form with programatically generated column headers.
The 3 options for columns are boolean | array | function.
By supplying false, the data returned is an array of arrays, which I would then need to transform into object literal form. Not ideal!
To supply an array of column names, I would already need to know how many columns there are... before it is parsed, which doesn't make sense. I could parse the first row to get the count, then start again supplying the array, but this seems clumsy.
I can supply a function which programmatically generates the column keys. E.g. column => column which doesn't help as a) there is no index supplied, and b) this then ignores the first line as it is assumed to be column headers being transformed into the desired column keys.
Is there a way trick to doing this that I've missed? Here are the two ways that seem clumsier and less efficient than necessary.
Parse 1 row, then parse all
// Obviously in actual use I'd handle edge cases
const colCount = csvParse(withoutHeader, {to_line: 1})[0].length;
// 3
const data = csvParse(withoutHeader, {columns: [...Array(colCount).keys()].map(i => `col{i}`)})
/*
[
{ col0: 'd1a', col1: 'd2a', col2: 'd3a' },
{ col0: 'd1b', col1: 'd2b', col2: 'd3b' }
]
*/
Parse into array of arrays, then convert
csvParse(withoutHeader).map(
row => row.reduce(
(obj, item, index) => {
obj[`col${index}`] = item;
return obj;
},
{}
)
)
/*
[
{ col0: 'd1a', col1: 'd2a', col2: 'd3a' },
{ col0: 'd1b', col1: 'd2b', col2: 'd3b' }
]
*/
To me it would be ideal to be able to specify columns as a function, which was given the column index as an argument instead of a header row.
I am trying to insert a href into one of my columns in DataTables but Im having some issues since I need the actual href to show my slug and then the full company name.
Example how it should be formatted: "company"
Real data: Toyota Cars.
I am using columns.render which seems to be the correct function but I can't wrap my head around how I can get 'company' between the a tags. The function does not even make use of the "data" specifier, instead it takes the data first in my ajax file which in this case is slug.
My DataTable.js file
ajax: '/api/datatable',
columns: [
{ data: 'slug' },
{ data: 'company' },
],
"columnDefs": [
{ targets: [0, 1], visible: true},
{ "targets": 0,
"data": "This doesnt even seem needed?",
"render": function ( data, type, row, meta ) {
return 'full company name';
}
}
],
I will go ahead and give an answer, based on the assumption that you are trying to merge values of 2 columns. If my assumption is not correct, please, update the question to clarify "expected vs actual" results.
You are using data parameter in render function. That parameter is based on the value you specified in columns.data. In your case (with target === 0), data will contain the value that DataTable got for { data: 'slug' } column.
If you want to merge values from different columns into one, then render function is the correct way to do it. However, instead of data, you should use row parameter, which contains all key-value fields for a row.
For example:
// ...
"targets": 0,
"data": null,
"render": function ( data, type, row, meta ) {
return ''+row.company+'';
// or whatever your row object key-value structure is
}
// ...
I have an array of object in Javascript that I want to subset based on key-value matches. In principle I want to access my array js_obj, change some objects where cond is true and then move on.
Let's say the array looks like this
js_obj = [{
word: "airport",
pic: "<img id='pic' src='../images/location/airport.png'/>",
cat: "location",
type: "undetermined"
}, {
word: "station",
pic: "<img id='pic' src='../images/location/station.png'/>",
cat: "location",
type: "undetermined"
}]
I now want to access js_obj where .word == "station" and of this selected object I want to change .type to "type_abc".
I was able to use each and select the object where the condition applies and change its .type as wanted, but I would like to do this within the original array. I do not simply want to filter out this object but find it, edit it, and leave the array in the modified state.
I found related posts referring to underscore.js but I think I didn't know which method to look for.
Can anybody help me with this indexing/subsetting problem?
Looping the array, checking the condition and modifying will keep it in the original array:
function modifyArrOfObjs(arr, key, condition, updateKey, updateValue) {
arr.forEach(function(obj) {
if (obj[key] == condition) {
obj[updateKey] = updateValue;
}
});
}
modifyArrOfObjs(js_obj, "word", "station", "type", "type_abc");