Is it possible to have widgets inside itself?

If you are requesting technical assistance with Twine, please specify:
Twine Version: 2.4.1
Story Format: Sugarcube V2

So I’m trying to transfer code I have in javascript to sugarcube and I was wondering if it’s possible to use a widget in itself kinda like how you would call a function within itself?

1 Like

Yes, it is.

If you mean recursively, like this…I don’t think so

<<widget "widget1">>
<<widget1>>
<</widget>>

Calling this by using <<widget1>> in a new passage will return errors




If you just want to use widgets inside of widgets, like this, then it’s possible.

<<widget "widget1">>
<<widget2>>
<</widget>>

<<widget "widget2">
<<print "this">>
<</widget>>

Calling this with <<widget1>> in a new passage will call <<widget2>>

Indeed you can call a <<widget>> inside itself.

I’ve done it, and it works as intended. The goal was to produce a random name from a list, and, if the reader doesn’t like the name, to offer to produce another (another random name, not another reader obviously).

Given $NomF, $NomM and $NomP all arrays.

<<widget "Noms">><span id="nom"><<if _args[0] == "1">><<textbox "$Nom" $NomM.random()>><<elseif _args[0] == "2">><<textbox "$Nom" $NomF.random()>><<else>><<textbox "$Nom" $NomP.random()>><</if>>
<<link "Proposer un autre nom">><<replace "#nom">><<Noms _args[0]>><</replace>><</link>></span><</widget>>
1 Like

You can use widgets recursively. The only issue is the same as with all recursion, recurse too deeply and you can overflow the stack.

1 Like

If I do something like this

<<widget "widget1">>
<<print "this">>
<<widget1>>
<</widget>>

And then call it with <<widget1>> I’d expect it to print “this” repeatedly.

Instead I get Error: <<widget1>>: error within widget code repeating. What have I done wrong?

If the issue is that it is repeating too deeply as you said, how do I limit it? (Now that I look more closely I see the “too much recursion” error at the very end).

This code looks like an infinite loop. There’s nothing to stop it.

First you need to determine when you want the action being done within the widget to stop being done.

Then you add a condition check (like the following) that will stop the widget being call recursively

eg. do you only want that action to be done a specific number of times? If so you could use a counter variable to determine when to stop calling the widget again.
note: you need to pre-initialise this counter variable sometime prior calling the widget the first time.

<<widget "widget1">>
	<<print "this">>
	<<set $counter += 1>>
	<<if $counter < 10>>
		<<widget1>>
	<</if>>
<</widget>>
1 Like

That works, thanks! I didn’t have any specific case in mind but it will be helpful in the future.