How to use fields from other (dynamically listed) tiddlers as parameters in a macro calculation?

491 views
Skip to first unread message

hubertgk

unread,
Nov 2, 2017, 11:57:47 AM11/2/17
to TiddlyWiki
Hi,

I have some tiddlers tagged 'tracker' and each of those tiddlers has the following 4 fields:

tracker_current_value
tracker_target_value
tracker_start_date
tracker_end_date

In a separate 'dashboard' tiddler, I'm listing these tracker tiddlers based on their tag, so:

<$list filter="[tag[tracker]] +[sort[name]]">

The 'dashboard' tiddler also has a 'TrackerStatus' macro I wrote that needs the 4 fields from the 'tracker' tiddlers as parameters. What I'm trying to achieve is perform the calculation using the 'TrackerStatus' macro on button click next to each 'tracker' tiddler that's listed.

The result of the calculation should then be stored in a separate data tiddler with the name of the individual tracker tiddler as its index and the result of the macro calculation as its value.

With the code below, I'm able to correctly populate the data tiddler with the indexes (names of tracker tiddlers), however the values are not populated properly. I suspect the problem is that the individual fields/parameters (<$set name=.. value=..>) are not transcluded before being sent to the 'Updated_status' macro for evaluation because they're outside of the list filter where the individual 'tracker' tiddlers are listed. As a result, the would-be parameters are blank.

The transclusion of the fields works correctly when I embed it <$list filter="[tag[tracker]] +[sort[name]]">HERE</$list>.

Is there a way around this? I apologise if that's not clear, English is not my first language. I'll be happy to clarify if more info is needed.

Here's my 'dashboard' tiddler:

\define Updated_status()
<<TrackerStatus $(tracker_start_date)$ $(tracker_end_date)$ $(currentVal)$ $(targetVal)$>>
\end

\define CurrentTiddler()
<<currentTiddler>>
\end

\define Button()
<$button class="button" tooltip="Refresh status">
<$action-setfield $tiddler="_data000" $index=$(CurrentTiddler)$ $value=$(Updated_status)$/>⥁ Status</$button>
\end

<$set name=currentVal value={{<currentTiddler>!!tracker_current_value}}>
<$set name=targetVal value={{<currentTiddler>!!tracker_target_value}}>
<$set name=tracker_start_date value={{<currentTiddler>!!tracker_start_date}}>
<$set name=tracker_end_date value={{<currentTiddler>!!tracker_end_date}}>

<p class="blur_in">
<table style="width:620px">
<$list filter="[tag[tracker]] +[sort[name]]">
<tr>
<td>
<$link to={{!!title}}><$view field="title"/
></$link>
<$list filter="[<currentTiddler>!days:modified[-3]]"> @@color:orange;^^probably needs updating^^@@</$list>
</td>
<td style="width:75px">
<$edit-text tiddler=<<currentTiddler>> field="tracker_current_value" rows="4" class="text-field"/
>
</td>
<td>
<div>
<<Button>>
</
div>
</td>
<td>
<$list filter='[[_data000]getindex<currentTiddler>]' emptyMessage="@@color:#cecece;(no data)@@">
<<currentTiddler>>
</
$list>
</td>
</
tr>
</$list>
</
table>
</p>

Thanks in advance for your suggestions.


Jed Carty

unread,
Nov 2, 2017, 12:14:07 PM11/2/17
to TiddlyWiki
If I understand what is going on correctly the problem is that macros don't necessarily trigger their own updates. So even if the value in a field field that is passed to the macro changes it won't necessarily make the output of the macro to change.

You don't actually show where in your code you use the Update_status macro or what TrackerStatus macro does, but normally the solution is to put the macro call inside a widget that will update when the inputs to the macro changes. A set widget is often enough for this.

This isn't directly related to your question, but you can probably simplify your macros a bit. If you always use the same field names than in your TrackerStatus macro you can use {{!!tracker_current_value}}, {{!!tracker_target_value}}, {{!!tracker_current_date}} and {{!!tracker_end_date}} inside the macro and then it will take those values from the tiddler where it is called and you don't need to use the Update_status macro to just call another macro.

hubertgk

unread,
Nov 2, 2017, 12:25:45 PM11/2/17
to TiddlyWiki
Thanks for your input Jed.


If I understand what is going on correctly the problem is that macros don't necessarily trigger their own updates. So even if the value in a field field that is passed to the macro changes it won't necessarily make the output of the macro to change.

I'm aware of this. That's why I'm trying to use the button to trigger the macro.


You don't actually show where in your code you use the Update_status macro or what TrackerStatus macro does

The Updated_status macro is a macro I've defined ad-hoc and its output is used as a parameter in the button, that's also defined as a macro. TrackerStatus, on the other hand, is a javascript macro I wrote that uses the 4 fields as calculations and outputs a fancy unicode 'icon' and whether I'm ahead/behind of schedule and by how many days, but there's no issue there, it works correctly.


If you always use the same field names than in your TrackerStatus macro you can use {{!!tracker_current_value}}, {{!!tracker_target_value}}, {{!!tracker_current_date}} and {{!!tracker_end_date}} inside the macro and then it will take those values from the tiddler where it is called and you don't need to use the Update_status macro to just call another macro.

That's right, however these fields are in separate tiddlers than the macro that's evaluating them.

Thanks again.

hubertgk

unread,
Nov 3, 2017, 5:40:08 AM11/3/17
to TiddlyWiki
OK, this appears a tough one to crack. I've changed the code a bit and now it's working well, though in a different way. Updates to status (via macro calculations) are now triggered by button click that's located in each tracker tiddler and not in the dashboard tiddler as I originally wanted it. A bit less convenient but at least it works now (requires 2 clicks instead of 1).

If anyone has suggestions as to how my original code could be improved to meet the original goal I'd still appreciate your suggestions.

Thank you again.
Hubert

PMario

unread,
Nov 3, 2017, 6:22:08 AM11/3/17
to TiddlyWiki
Hi,

I only did read the first post and didn't do any tests with your code. ... So the following is just a guess..Did you try:

\define bAction()

<$action-setfield $tiddler="_data000" $index=$(CurrentTiddler)$ $value=$(Updated_status)$/>
\end

\define Button()
<$button actions=<<bAction>> class="button" tooltip="Refresh status">
Status</$button>
\end




as described here: http://tiddlywiki.com/#ActionWidgets

have fun!
mario

hubertgk

unread,
Nov 3, 2017, 6:34:54 AM11/3/17
to tiddl...@googlegroups.com
Hi PMario, thanks for your response.

Your code for the button works well, the same as mine. The problem is not the button though and I apologise if the way I've described my original problem is not clear enough. I'm not quite sure how to make it clearer.

In a nutshell, the problem is that the values of the following must be set to match the fields of the respective (separate) tracker tiddlers, where the tracker tiddlers are listed using a filter:


<$set name=currentVal value={{<currentTiddler>!!tracker_current_value}}>
<$set name=targetVal value={{<currentTiddler>!!tracker_target_value}}>
<$set name=tracker_start_date value={{<currentTiddler>!!tracker_start_date}}>
<$set name=tracker_end_date value={{<currentTiddler>!!tracker_end_date}}>

It's likely that the problem is incorrect scope or, quite likely, that TiddlyWiki is unable to use tiddlers dynamically listed using a list filter as parameters for a macro.

Best,
Hubert

PMario

unread,
Nov 3, 2017, 6:55:15 AM11/3/17
to TiddlyWiki
Did you try the vars-widget http://tiddlywiki.com/#VarsWidget instead of the set-widget.

Vars is much newer and behaves slightly different.

-m

Jeremy Ruston

unread,
Nov 3, 2017, 8:14:07 AM11/3/17
to tiddl...@googlegroups.com
Hi Hubert

On 3 Nov 2017, at 10:34, hubertgk <hube...@gmail.com> wrote:

<$set name=currentVal value={{<currentTiddler>!!tracker_current_value}}>
<$set name=targetVal value={{<currentTiddler>!!tracker_target_value}}>
<$set name=tracker_start_date value={{<currentTiddler>!!tracker_start_date}}>
<$set name=tracker_end_date value={{<currentTiddler>!!tracker_end_date}}>

That’s the wrong syntax for transcluding a field from the current tiddler.

The syntax for a transcluded attribute allows for the following possibilities when transcluding from a tiddler field:

{{MyTiddlerTitle!!my-field-name}}
{{!!my-field-name}}
{{MyTiddlerTitle}}

In the first case, both the tiddler and the field are specified. In the second case, the tiddler isn’t specified and so defaults to the value of the currentTiddler variable. And in the third case, the field isn’t specified and so defaults to “text”.

So, perhaps try:

<$set name=currentVal value={{!!tracker_current_value}}>
<$set name=targetVal value={{!!tracker_target_value}}>
<$set name=tracker_start_date value={{!!tracker_start_date}}>
<$set name=tracker_end_date value={{!!tracker_end_date}}>

Best wishes

Jeremy.

hubertgk

unread,
Nov 3, 2017, 9:01:47 AM11/3/17
to tiddl...@googlegroups.com
Thank you very much for this Jeremy.

With the corrected syntax, {{!!my-field-name}}, the field transclusions are derived from the current tiddler that's understood as the very tiddler that has the macro and the transclusions themselves (the 'dashboard' tiddler in my original description). I'm aware that this is expected behaviour.

What I would need is transclude the fields of other tiddlers ('tracker' tiddlers), without explicitly specifying those tiddlers' names -- the name should be provided by the list filter:


<$list filter="[tag[tracker]] +[sort[name]]">

This is why I was trying to use <currentTiddler> as I was hoping to transclude the fields of a <currentTiddler> that's currently listed by the list filter. When I transclude fields using <currentTiddler> within the above list filter, the respective fields are transcluded correctly but when I use <$set> within the above list filter, the set values are no longer available to the macro that's defined outside of the above <$list></$list>.

I'm sorry if that's a bit convoluted way of thinking, I'm still learning TW and though I've been experimenting a lot, I'm still making many basic mistakes in the process. That said, I'm amazed at what TW can do. Thank you Jeremy for creating and maintaining such an amazing tool!

@PMario, thanks for your suggestions, they definitely sound interesting. I'll experiment with them in the future; unfortunately they don't seem to help in my use case.

Best regards,
Hubert

Jeremy Ruston

unread,
Nov 3, 2017, 9:18:02 AM11/3/17
to tiddl...@googlegroups.com
Hi Hubert

Apologies, I’m struggling a little to understand what you’re trying to do, and the context for the original code. Perhaps you could post an absolutely minimal test case that illustrates what you’re trying to do? The code in the original post has a bunch of styling etc. that gets in the way of understanding it, and it looks like it might be incomplete (eg there’s no closing </$set>).

Perhaps the problem is just that you want to set the variables curentVal, targetVal etc. such that they can be accessed within the Updated_status macro? If so, you should be able to wrap set widgets around the <$button> widget within the Button macro.

One little thing I noticed trying to read your original code is that you’ve got a macro:

\define CurrentTiddler()
<<currentTiddler>>
\end

But then you are invoking it via text substitution:

<$action-setfield $tiddler="_data000" $index=$(CurrentTiddler)$ $value=$(Updated_status)$/>⥁Status</$button>

Because there’s no wikification done during text substitution, that is equivalent to:

<$action-setfield $tiddler="_data000" $index=<<currentTiddler>> $value=$(Updated_status)$/>⥁Status</$button>

Best wishes

Jeremy


-- 
You received this message because you are subscribed to the Google Groups "TiddlyWiki" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywiki+...@googlegroups.com.
To post to this group, send email to tiddl...@googlegroups.com.
Visit this group at https://groups.google.com/group/tiddlywiki.
To view this discussion on the web visit https://groups.google.com/d/msgid/tiddlywiki/67ebd680-0d24-4798-aece-c7f21472d80b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

hubertgk

unread,
Nov 3, 2017, 6:26:20 PM11/3/17
to TiddlyWiki
Apologies for the messy code and for including the irrelevant bits.

Perhaps the problem is just that you want to set the variables curentVal, targetVal etc. such that they can be accessed within the Updated_status macro? If so, you should be able to wrap set widgets around the <$button> widget within the Button macro.

That's exactly what I was trying to do, except that the values for the variables should come from fields of other tiddlers, and not from the defining tiddler. At last, I finally got my code working by wrapping the <$set> definitions in a <$list> filter. My initial conclusion was that if a variable is <$set> and wrapped in a <$list> filter then its value will not be available to a macro defined outside of that list -- this is of course incorrect. It was, again, my own syntax error.

Jeremy, thank you again for your pointers and help. I did not correctly close the </$set> widgets or just left them open. Also, the <<currentTiddler>> definitions were reduntant, so I removed them altogether and got a cleaner code.

Anyway, here's the working code (cleaned up a bit), just for the record. On button click, the macros calculate a result using fields from tiddlers listed by the <$list> filter, save that result in a data tiddler, which then is transcluded next to the button that was clicked. Issue resolved :).

Thank you again Jeremy, PMario and Jed Carty for all your invaluable help and advice.

\define Updated_status()
<<TrackerStatus $(tracker_start_date)$ $(tracker_end_date)$ $(currentVal)$ $(targetVal)$>>
\end

\define bAction()
<$action-setfield $tiddler="_data000" $index=<<currentTiddler>> $value=$(Updated_status)$/>
\end

\define Button()
<$button actions=<<bAction>>>
⥁ Status</$button>
\end



<table>
<$list filter="[!days:tracker_start_date[-1]][days:tracker_start_date[0]] +[tag[tracker]] +[sort[tracker_end_date]]">
<$set name=currentVal value={{!!tracker_current_value}}>
<$set name=targetVal value={{!!tracker_target_value}}>
<$set name=tracker_start_date value={{!!tracker_start_date}}>
<$set name=tracker_end_date value={{!!tracker_end_date}}>
<tr>
<td>
<$link to={{!!title}}><$view field="title"/></$link>
</td>
<td>
<$list filter='[[_data000]getindex<currentTiddler>]' emptyMessage="@@color:#cecece;(no data)@@"><<currentTiddler>></$list>
</td>
<td>
<<Button>>
</td>
</tr>
</$set>
</$set>
</$set>
</$set>
</$list>
</table>

Best regards,
Hubert

TonyM

unread,
Nov 3, 2017, 6:40:17 PM11/3/17
to TiddlyWiki
Without reading the whole thread I must ask if you are giving due regard to closures such as </$set>?

Unclosed you get odd results, closed ends the value. Since closure is unnamed you need to be clear the balance of opens and closes. This forces certian structures you need to be clear about.

Also put each closure on its ownline.

just a little advice.
Tony

Reply all
Reply to author
Forward
0 new messages