Looping through tagging hierarchy to bulk update a field

172 views
Skip to first unread message

Pall Sigurdsson

unread,
Feb 28, 2021, 4:27:45 PM2/28/21
to TiddlyWiki
Hello,

This is my first post here. I discovered TiddlyWiki last November and got hooked by its power and beauty. I challenging myself into programming something which was supposed to be very simple in the beginning but who knew that this would become so addictive? Anyhow, I have a question I'm hoping someone here could help me with.

How can one loop through tiddlers which are two levels downstream in the tag-hierarchy or further? I already figure out how to copy a field value from the current tiddler to all tiddlers which are tagging it and which also have the tag 'task' but what I think I need help with is to propagate the value 2-3 levels further.

The following code fragment reads the task_visibility (custom) field of the current tiddler and applies it to the next level below (only to tiddlers which are also tagged with 'task').

<$set name="taskVisibilityValue" value={{!!task_visibility}}>
<$list filter="[tag[task]tag<currentTiddler>]">
<$action-setfield $field="task_visibility" $value=<<taskVisibilityValue>> >
</$list>

Note: The filter above can be replaced with "[all[current]tagging[]tag[task]]" - it works just the same.

One of the things I tried for taking this one level further down the task hierarchy was nesting the lists:

<$set name="taskVisibilityValue" value={{!!task_visibility}}>
<$list filter="[all[current]tagging[]tag[task]]">
<$action-setfield $field="task_visibility" $value=<<taskVisibilityValue>> >
<$list filter="[all[current]tagging[]tagging[]tag[task]]">
<$action-setfield $field="task_visibility" $value=<<taskVisibilityValue>> >
</$list>
</$list>

This code still works only on the first level below the current tiddler. Does anyone know how to apply this to the next level below the first child level (and further)?

I'm also wondering whether it is a good idea to do this (or how far down to go), whether there are performance issues to be expected with a loop like this, when the hierarchy below the current tiddler might contain dozens of tiddlers.

Best regards,
Pall
- Currently on version 5.1.23

Pall Sigurdsson

unread,
Feb 28, 2021, 4:45:26 PM2/28/21
to TiddlyWiki
Oops, I missed the closing </$set> in both code fragments but that is not the issue.

Soren Bjornstad

unread,
Feb 28, 2021, 6:29:25 PM2/28/21
to TiddlyWiki
Your first $list widget is resetting the current tiddler, so in your second $list widget the all[current] doesn't mean the same thing as it did in the first. If I'm understanding your tiddler layout correctly, I think you should be closing the first $list widget prior to starting the second one.

As for a better way, the kin filter can be used to merge all the levels of a multi-level hierarchy into a single list, which would prevent you from having to try to make this recursive to handle an arbitrary number of levels. I think you should be able to get that to work here.

(Also, pretty sure you need a $button widget somewhere if you want to trigger anything, unless I'm missing something – but maybe you just left that out for brevity.)

Pall Sigurdsson

unread,
Mar 1, 2021, 3:20:46 AM3/1/21
to TiddlyWiki
Thanks, Soren, for the explanation and suggestions. My understanding of how the filters work is unfortunately very limited. I have been doing a lot of trial and error, sometimes finding a solution eventually, but too often without understanding of why it worked. Instead of continuing with that approach, I think asking a question and getting specific answers will lead to an increased understanding and it is already starting to pay off :)

The looping operation I described in the last post is a macro triggered by a Select widget. I use the actions attribute of the Select widget to call this code as a macro. Closing the first list widget (for the first level) before running the same operation at the next level was actually the first thing I attempted but I didn't manage to get it to work. The second list widget in the following code does not work.


<$set name="taskVisibilityValue" value={{!!task_visibility}}>
<$list filter="[all[current]tag[task]tagging[]]">

<$action-setfield $field="task_visibility" $value=<<taskVisibilityValue>> >
</$list>
<$list filter="[all[current]tag[task]tagging[]tagging[]]">

<$action-setfield $field="task_visibility" $value=<<taskVisibilityValue>> >
</$list>
</$set>

What am I doing wrong?

Note: The kin filter actually looks interesting and I might try it out if I will not solve it with core filter functionality or if I find more use cases for it.

Best regards,
Pall

Mat

unread,
Mar 1, 2021, 7:24:18 AM3/1/21
to TiddlyWiki
@psigu...

TL:DR; Is this your question:

>How can one loop through tiddlers which are two levels downstream in the tag-hierarchy or further?

If that is your question, I will attempt to reply. If you have some other complex question, I suggest you split it up into distinct questions, perhaps separate posts, so that they can more easily be dealt with.

<:-)

Pall Sigurdsson

unread,
Mar 1, 2021, 8:15:46 AM3/1/21
to TiddlyWiki
Yes, Mat. That's the question :)

Mat

unread,
Mar 1, 2021, 4:12:46 PM3/1/21
to TiddlyWiki
OK, so you just nest listwidgets like so:

<$list filter="[tag[mytag]]">
<$list filter="[tag<currentTiddler>]">

</$list>
</$list>

Just add another for each level down. Each new layer inside would refer to <currentTiddler>.

<:-)

Pall Sigurdsson

unread,
Mar 1, 2021, 5:59:22 PM3/1/21
to tiddl...@googlegroups.com
Hi Mat,
It works a little bit too well. The field update is applied everywhere downstream in the hierarchy, not only the level immediately below and not limited to the branch leading down from the current tiddler.
So let's say I apply it at level 2. Using only three nested list widgets I was able to apply it five levels down (I didn't look further) and it was also updating tiddlers in other branches.
How can I restrict the loop to the tag hierarchy below the current tiddler?
Regards,
Pall

--
You received this message because you are subscribed to a topic in the Google Groups "TiddlyWiki" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/tiddlywiki/ECYrNcJ8QsQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to tiddlywiki+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/tiddlywiki/dd6ca765-68d6-4054-8c51-419922994d4dn%40googlegroups.com.

Mat

unread,
Mar 1, 2021, 7:06:25 PM3/1/21
to TiddlyWiki
I suggest you set up a demo on tiddlyhost.com . If anyone is to test things out for you they'll have to create the code and dummy tiddlers etc and this is just too much for people to do. It will also be much easier to understand what you mean.

<:-)

Pall Sigurdsson

unread,
Mar 2, 2021, 3:31:31 AM3/2/21
to tiddl...@googlegroups.com
Yes, it's only fair that I'll do that work :)  Thanks for the time you have spent on this so far. I'm planning to set something up soon on Tiddlyhost and will reply back when it's ready.
// Pall

Pall Sigurdsson

unread,
Mar 2, 2021, 6:14:24 PM3/2/21
to tiddl...@googlegroups.com
Hi,
Here is a tiddlyhost site with the problem I was trying to explain above: palltest.tiddlyhost.comI
I hope it's clearer now what I'm trying to achieve. I set it up with a reset button so the field of all tiddlers can be reset after every failed attempt to solve it.
// Pall


Mat

unread,
Mar 2, 2021, 7:12:19 PM3/2/21
to TiddlyWiki
\define change-inner(tid)
   <$list filter="""[tag[$tid$]tag[task]]""">
      <$action-setfield task_visibility="$(taskVisibilityValue)$" />
      <$macrocall $name=change-inner tid=<<currentTiddler>>/>
</$list>
\end

\define changeVisibility()
<$vars taskVisibilityValue={{!!task_visibility}}>
   <$list filter="""[tag<currentTiddler>tag[task]]""">
      <$action-setfield task_visibility=<<taskVisibilityValue>> />
      <$macrocall $name=change-inner tid=<<currentTiddler>>/>
   </$list>
</$set>
\end

\define visibilitySelect()
Visibility: 
<$select field="task_visibility" actions=<<changeVisibility>> >
<option value=0>0</option>
<option value=10>10</option>
<option value=20>20</option>
<option value=30>30</option>
<option value=40>40</option>
</$select>
\end


Selecting a value should propagate it downstream the tag hierarchy only from this tiddler (only tiddlers tagging this tiddler and so on). This should be true only for tiddler which are also tagged with 'task'.

<<visibilitySelect>>

Pall Sigurdsson

unread,
Mar 3, 2021, 2:23:31 AM3/3/21
to tiddl...@googlegroups.com
Works like a charm! Many many thanks!

I had no idea that a macro could be called from within itself and that this would be safe.
Should I leave the closing </$set> in the changeVisibility as it is or change it to </$vars>? I doesn't appear to make any difference.

Best regards,
Pall

Mat

unread,
Mar 3, 2021, 4:18:25 AM3/3/21
to TiddlyWiki
I had no idea that a macro could be called from within itself and that this would be safe.

Yeah, it's a programming concept called recursion.
 
Should I leave the closing </$set> in the changeVisibility as it is or change it to </$vars>? I doesn't appear to make any difference.

No change it to vars.

<:-) 
Reply all
Reply to author
Forward
0 new messages