For loops and dataviewjs

Things I have tried

I have searched, and searched this Obsidian forum, and not found anything that leads to an answer.

The following threads come close, perhaps:

https://forum.obsidian.md/t/using-a-dataview-query-how-do-you-display-only-those-tasks-which-have-a-value-for-some-field/39149/4

@scholarInTraining helped here, but I was unable to pursue their suggestion before the thread was closed and so couldn’t ask follow up questions.

What I’m trying to do


In summary: I want return all the tasks in my vault which are tagged with tags associated with the current page’s tag field.


I’m trying to get some help coding the following ideas into dataviewjs. I simply don’t know enough about javascript to make it work… I hope what follows, clearly communicates the logic of what I want to do, generally speaking from an abstract point of view.

Read this for context…

Imagine the current page, called cp, belongs to an obsidian vault called V. Pretend cp has a field tags:: whose associated array of elements are #a #b #c .

Thus, in the abstract cp would look as follows:

tags:: #a #b #c

(Let’s say an arbitrary member of tags:: is called x. This means means when I mention x below, I’m just referring to one of #a, #b, or #c in tags:: of cp, and it really doesn’t matter which one.)

Also, imagine there is a set of tasks T strewn throughout vault V appearing randomly on V’s pages . i.e. not in a predictable section on a given page v. Imagine the text of the tasks is varied, and let it be true that most of these tasks are tagged.

For a given task t in T, the set of tags G associated with t is pretty open ended.

So, for example t could be as follows where G = {#a, #b, #c, #d, #e}:

- [ ] blah blah blah #a  #b  #c  #d  #e       Example 1

Or, t could be like this, where G = {#a, #s, #d, #f}:

- [ ] blah blah blah and more blah #a #s #d #f    Example 2

A subset of T, let’s call it S, is tagged with #a #b #c , the array elements associated with tags:: in cp.

An arbitrary task s in S might look like this, where G actually (loosely speaking) equals tags:: :

- [ ] blah blah #a  #b  #c      Example 3

Or, where tags:: is (loosely speaking, again) a subset of G:

- [ ] blah blah #a  #b  #c  #d  Example 4

(It follows that the task in Example 1 is a member of S because it is tagged with #a #b #c . It has additional tags, but that is incidental. )

So far, we have a vault V, whose current page cp has a field tags:: whose associated array is #a #b #c . It is also the case that some of V’s pages have tasks on them, and some of these tasks, the set S, are tagged (but not exhaustively) with #a #b #c.

My question is this:

How do you query V with dataviewjs (or dataview, if that’s possible) and return a list of s in S as defined above?

In other words, how do you return the tasks which are such that for each tag x in tags:: of cp, x is also a member of G (the tags associated with s) ?


In summary: I want return all the tasks in my vault which are tagged with tags associated with the current page’s tag field.


I really appreciated any suggestions or thoughts. It seems I need to use a for loop, but I don’t know how to implement them in dataviewjs. If it were python, I could code this, but I don’t know where to start with dataviewjs.

Thanks for any help.

1 Like

If I understand your post correctly, this is the code:

```dataviewjs
dv.taskList(dv.pages().file.tasks
  .where(t => t.tags.length && t.tags.filter(x => dv.current().tags.includes(x)).length))
```

This will display tasks from any of your notes which contain any of the tags in your current note.

To make it more verbose, here are all the parts separated:

```dataviewjs
const allTasks = dv.pages().file.tasks

const myTags = dv.current().tags

const filteredTasks = allTasks
.where(t => t.tags.length && t.tags.filter(x => myTags.includes(x)).length)

dv.taskList(filteredTasks)
```

This part is computing the intersection between two arrays:

t.tags.length && t.tags.filter(x => myTags.includes(x)).length
1 Like

As you know I’m not versed in JS but I like to learn something with your posts.

  1. My first observation is related with the current tags.
    In the format tags:: #a #b #c this field is a string, not an array. Maybe it’ll be necessary to write in format tags:: #a, #b, #c
  2. I think they want to check if the tasks tags (an array) includes another array (#a, #b, #c)

Hi @AlanG,

Thanks for considering my post.

The code you is suggested is almost there, however unfortunately it returns tasks that have as few as a single tag in tags::.

For example, the query will return the following

- [ ] blah blah #a

or,

- [ ] blah blah blah #b

I only want to see tasks that have all three tags associated with tags:: in cp.

For example,

- [ ] blah blah blah #a #b #c

or,

- [ ] blah #a #b #c

Thanks you so much for thinking about it, and also for teasing out the code and explaining what it is doing. It helps me learn dataviewjs.

Good point, as @mnvwvnm mentions, you need commas in your tags line, like this:

Here is with all tags from the current note required to be present in the task:

```dataviewjs
dv.taskList(dv.pages().file.tasks 
  .where(t => dv.current().tags.every(x => t.tags.includes(x))))
```
2 Likes

Thanks. Reversing the arrays comparison order and add every

Hi @mnvwvnm,

Thanks for your observations.

Regarding observation 1, I tried inserting commas between the tags in tags:: of cp as you suggested. The code generously provided by @AlanG continued to return tasks that have as few as a single tag from tags:: which is not what I’m after. I want to return those tasks in my vault that are tagged with all the tags in tags::. The returned tasks will possibly be tagged with more tags than are associated with tags::, and that’s okay; but of all the tags appended to a returned task, the tags:: of cp must by included.

I’m sorry, I don’t understand what you mean in your second observation.

Thanks for looking at my post.

I think the last code provided by @AlanG works. And it is related with the second observation.

2 Likes

You need the code from my most recent post. The first code was designed to return tasks with ANY tags not ALL tags

1 Like

Well done @AlanG!

Thank you so much! You’re a wizard!

2 Likes

Thanks @mnvwvnm!

I really appreciate your input in supporting @AlanG to find a solution. Well done!

1 Like

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