Action widgets are a special type of widget that have no visual appearance but perform an action when triggered (such as sending a message, navigating to a tiddler, or changing the value of a tiddler). Action widgets are used in association with other widgets that trigger those actions (for example, the ButtonWidget).
The following action widgets are provided:
- action-confirm
- action-createtiddler
- action-deletefield
- action-deletetiddler
- action-listops
- action-log
- action-navigate
- action-popup
- action-sendmessage
- action-setfield
- action-setmultiplefields
There are two ways to use action widgets:
- Placing them within an action string attribute (typically called
actions
) on the triggering widget (this is the preferred way) - Embedding the actions within the triggering widget (an older technique that is now deprecated)
Using action string attributes
The action widgets are passed as a string to the actions
attribute of the triggering widget. Usually, it is more convenient to use a macro to assign the action widgets to a variable. For example, here is a button that triggers two actions of sending different messages:
\define my-actions()
<$action-sendmessage $message="tm-home"/>
<$action-sendmessage $message="tm-full-screen"/>
\end
<$button actions=<<my-actions>>>
Click me!
</$button>
Directly embedding action widgets
The action widgets need not be immediate children of their triggering widget, but they must be descendents of it. The actions are performed in sequence. Here is the above example rewritten to use embedding:
<$button>
<$action-sendmessage $message="tm-home"/>
<$action-sendmessage $message="tm-full-screen"/>
Click me!
</$button>
Action Execution Modes
Introduced in v5.2.0 The default behaviour of action widgets has some peculiarities that often cause confusion. There is now an improved mode that simplifies how things work, but due to BackwardsCompatibility constraints, it must be explicitly engaged in order to take advantage of it.
The peculiarities relate to the way that the results of previous action widgets are available to subsequent action widgets. By default, action widgets are refreshed before each execution which ensure that they reflect the results of previous actions. However, ordinary widgets are not updated in the same way.
In the following contrived example, a button triggers a series of actions that should result in the string foo
being assigned to the text field of the tiddler ActionTestTiddler. However, it fails to produce the expected result because the <$set>
widget is not refreshed with the new value of ActionTestTiddler after the execution of the first <$action-setfield>
widget.
\define actions()
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value="FOO"/>
<$set name="newvalue" value={{{ [{ActionTestTiddler}lowercase[]] }}}>
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<newvalue>>/>
</$set>
\end
Current value of ActionTestTiddler: {{ActionTestTiddler}}
<$button actions=<<actions>>>
Click me
</$button>
That renders as:
Current value of ActionTestTiddler:
The new behaviour avoids these problems by refreshing all widgets before execution, not just action widgets. It is engaged by running the actions in a scope that includes the variable tv-action-refresh-policy
set to the value always
. (The default value for tv-action-refresh-policy
is once
).
The assignment can be done within an action string, or via a local variable declaration containing the widget triggering the action.
The example above works as expected with the addition of tv-action-refresh-policy
:
\define tv-action-refresh-policy() always
\define actions()
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value="FOO"/>
<$set name="newvalue" value={{{ [{ActionTestTiddler}lowercase[]] }}}>
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<newvalue>>/>
</$set>
\end
Current value of ActionTestTiddler: {{ActionTestTiddler}}
<$button actions=<<actions>>>
Click me
</$button>
That renders as:
Current value of ActionTestTiddler: