Action-setfield not working in a button widget

Hello all!

I’m working on some UI elements and as part of the edition UI of a tiddler (of a Character). I have the following code in that Character tiddler:

<$let spellbookname={{{ [<currentTiddler>get[draft.title]addsuffix[/spellbook]] }}}> <!-- using draft.title instead of title because the button appears only when editing the Character tiddler, thus renaming it with 'draft of' -->
<$macrocall $name="create-new-spellbook-button-char" title=<<spellbookname>> navigate="no"/></$let>

The create-new-spellbook-button-char procedure is supposed to create a button that if pressed will create a new tiddler titled <<spellbookname>> and NOT navigate to it, which works well. However, I also want this button to give the value <<spellbookname>> to the spellbook field that is on the Character tiddler the button is clicked from.

Here are the rest of the macros I used for that button:

\function spellbook.tags() GURPS Spellbook +[join[ ]format:titlelist[]]

\procedure spellbook.button.actions.char()
<$macrocall $name='create-new-spellbook' title=<<title>> navigate='no'/>
\end

\procedure create-new-spellbook(title, navigate:yes)
<$action-createtiddler  $basetitle=<<title>> tags=<<spellbook.tags>> type="application/x-tiddler-dictionary" icon="$:/GURPS/icons/spellbook">
	<% if [<navigate>match[yes]] %><$action-navigate $to=<<createTiddler-title>>/><% endif %>
</$action-createtiddler>
\end

\procedure create-new-spellbook-button-char(title)
<$button actions=<<spellbook.button.actions.char>>>
<$action-setfield $tiddler=<<currentTiddler>> $field='spellbook' $value=<<title>>/>
{{$:/GURPS/icons/spellbook}}&nbsp;New spellbook
</$button>
\end

I feel like it’s all wobbly code, but since the main part (creating the spellbook dictionary tiddler with the correct name and tag) works well, I’m left wondering why the button’s immediate child widget <$action-setfield> doesn’t change the field as intended?

You can take a look directly at the TW here

A brief scan makes me ask where is the rest of the relevant code?, you don’t show how the above is invoked and how navigate gets set to yes. Remove that conditional in create-new-spellbook and see if that works.

I reorganized your code a bit (starting from the macro tiddler in your demo wiki) — does this work as intended?

\procedure create-new-spellbook-button(title)
<$button actions=<<spellbook.button.actions>>>
	{{$:/GURPS/icons/spellbook}}&nbsp;New spellbook
</$button>
\end

\procedure create-new-spellbook-button-char(title)
<$button actions=<<spellbook.button.actions.char>>>
	{{$:/GURPS/icons/spellbook}}&nbsp;New spellbook
</$button>
\end

\procedure spellbook.button.actions() <<create-new-spellbook navigate:"yes">>
\procedure spellbook.button.actions.char() <<create-new-spellbook navigate:"no">>

\procedure create-new-spellbook(navigate:"yes")
\function spellbook.tags() GURPS Spellbook +[join[ ]format:titlelist[]]
<$action-createtiddler
	$basetitle=<<title>>
	tags=<<spellbook.tags>>
	type="application/x-tiddler-dictionary"
	icon="$:/GURPS/icons/spellbook"
>
	<$action-setfield $field=spellbook $value=<<createTiddler-title>> />
	<% if [<navigate>match[yes]] %><$action-navigate $to=<<createTiddler-title>>/><% endif %>
</$action-createtiddler>
\end

I moved the $action-setfield from the $button contents into the create-new-spellbook procedure used by the button actions. This lets us use the <<createTiddler-title>> variable to set the field to the correct value. <<title>> alone won’t necessarily match the name of the newly created tiddler, as it doesn’t include the number(s) added to create a unique title.

As a minor note, I also removed the title parameter from the inner procedures. You define <<title>> when you call the outer procedure (create-new-spellbook-button or create-new-spellbook-button), so it’s automatically available to all child procedures; you don’t need to use title=<<title>> to pass it along.

Finally, I moved the spellbook.tags function inside the create-new-spellbook procedure that uses it, just to keep things organized.

  • I left the function as you wrote it in my code above, but if the only tag want to add to the new data tiddler is “GURPS Spellbook”, you could simplify it to \function spellbook.tags() [[Gurps Spellbook]], or just use tags="[[GURPS Spellbook]]" in the $action-createtiddler and skip the function altogether.

It does! However, the reason I did put the $action-setfield in the <$button> originally was so that I could use create-new-spellbook in tiddlers that are not Character tiddlers (and don’t have the spellbook field) as well. With that rewrite, I technically still can, but I’ll get unwanted spellbook fields assigned everywhere :stuck_out_tongue_winking_eye:

I imagine that I could simply add a conditional around the <$action-setfield> in create-new-spellbook to detect whether or not the procedure is called from inside a Character tiddle (<% if [<currentTiddler>tag[Character]] %><$action-setfield $field=spellbook $value=<<createTiddler-title>> /><% endif %>) to take care of that then?

N.B: the reason I went the function route with the tags is because in future cases I’m planning for those Tiddler creation buttons, that will be using this same structure, multiple tags will be needed. For example, the button to create Modifiers tiddlers will not only need the “GURPS Modifier” tag but also either “GURPS Limitation” or “GURPS Enhancement” depending on what kind of Modifier is being created. So I lazily architected like this so I could copy/paste the whole thing and just change the relevant parts (which, I realize, isn’t really saving me much time anyways…)

Hello @TW_Tones and thanks for your answer :slight_smile:
I’m not sure what missing relevant code you are referring to? Everything starts in the Character tiddler where it is invoked with the first code section:

<$let spellbookname={{{ [<currentTiddler>get[draft.title]addsuffix[/spellbook]] }}}> <!-- using draft.title instead of title because the button appears only when editing the Character tiddler, thus renaming it with 'draft of' -->
<$macrocall $name="create-new-spellbook-button-char" title=<<spellbookname>> navigate="no"/></$let>

navigate would be set to “yes” here if needed, or by default if omitted as defined by the procedure through \procedure create-new-spellbook(title, navigate:yes)

I was confused too because I stopped to look at the code and didn’t realise that there was a link to the wiki further down.

Yes, I think using another conditional is the best way to handle it, since $action-setfield has to be inside $action-createtiddler.

Alternatively, since locally defined variables take precedence over global definitions, you could redefine that procedure only in the tiddler where you want to use a different version. As long as the name remains the same, it will work seamlessly with your other global procedures.

1 Like

I didn’t know that, it’s an interesting trick to keep in mind! Most of my stuff is global :stuck_out_tongue_winking_eye: