Sorting groups in Dataview JS

Heya,

How can groups be sorted in dataviewjs?

Tried with standard array manipulation but to no avail (e.g. using Array.reverse()) so wondering if these are Dataview arrays instead and need to convert them into normal arrays first, then back?

You can also explicitly convert a normal JavaScript array into a Dataview array using dv.array(<array>). If you want to convert a Data array back to a normal array, use DataArray#array()Data Arrays - Dataview


The setup:

page-1:

---
title: "page 1"
status: "archived"
tags: "note"
---

page-2:

---
title: "page 2"
status: "published"
tags: "note"
---

Current Query:

for (let group of dv.pages("#note").groupBy(p => p.status)) {
    dv.header(3, group.key);
    dv.table(
		["Title", "Status", "Tags"],
        group.rows
            .sort(k => k.file.link, 'desc')
            .map(k => [(k.title).link(k.file.link), k.status, k.tags]))
}

Current Output:

Archived

Name Status Tags
page 1 Archived #note

Published

Name Status Tags
page 2 Published #note

Desired Output:

Published

Name Status Tags
page 2 Published #note

Archived

Name Status Tags
page 1 Archived #note

Hi.

My knowledge about JS is almost zero (I’m more a DQL user). So, I’m in a strange position about give an answer to someone who knows certainly knows much more than I do.

Doing some research in Discord channel I found a solution (don’t ask me the logic) that can work to you:

```dataviewjs
let groups = dv.pages("#note").groupBy(p => p.status)

for (let group of groups.sort(g => g.key, 'desc')) {
    dv.header(3, group.key);
    dv.table(
		["Title", "Status", "Tags"],
        group.rows
            .sort(k => k.file.link, 'desc')
            .map(k => [(k.title).link(k.file.link), k.status, k.tags]))
}

```
2 Likes

Yess perfect!!! Thank you so much :blush:

Taking it a step further this setup allows to specify a custom sorting order:

let groups = dv.pages("#note").groupBy(p => p.status);

// define custom sorting
const sortBy = ['draft', 'published', 'archived'];

/* 
  Convert array to object: item:index ("draft":0, "published":1...)
  this can be skipped and manually constructed in the og array
  but this way is cleaner.
*/
const sortByObject = sortBy.reduce((obj, item, index) => { obj[item] = index
  return obj
}, {})

// perform sorting
groups.values.sort((a, b) => sortByObject[a["key"]] - sortByObject[b["key"]]);

// render table
for (let group of groups) {
    dv.header(3, group.key);
    dv.table(
		["Title", "Status", "Tags"],
        group.rows
            .sort(k => k.file.link, 'desc')
            .map(k => [
`[[${k.file.name}|${k.title}]]`, k.status, k.tags]))
}
3 Likes

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.