Unexpected behavior with ts-raw alongside other slot-fills (duplicated fills)

Trying to learn my way around custom widgets with slot and fill values, I came across this anomaly. Perhaps there’s some typo in my setup, but this behavior (doubling of overridden slot values) is odd, enough to ask y’all whether there’s a bug in the code.

My troubleshooting got only as far as noticing that removing the ts-raw slot takes away the weirdness. Also, problem doesn’t appear if I keep the ts-raw slot AND I fill it explicitly, e.g. <$fill $name="ts-raw">Play</$fill>. Still, I don’t see how the doubling effect makes sense:

First (“TODAY”) invocation works fine. Second (with slot fills for TOMORROW) is strange:

Here’s my live example: Quick demo — showcasing…

Stripping away red herrings, here’s absolute minimum code to show unexpected behavior at tw-com:

\widget $my.widget()
<$slot $name="ts-raw">Default</$slot>
<$slot $name="extra">Result</$slot>
\end

<$my.widget>
	Bespoke
<$fill $name="extra">Custom</$fill>
</$my.widget>

Result:

Bespoke Custom Custom

I smell a
:beetle:

Not a bug, or at least, not a bug with the ts-raw slot. You can actually understand this by substituting each slot with its fill value.

As you know, if you use the ts-raw slot without explicitly filling it, then it gets filled with the contents of the widget call - including the additional $fill widgets that you wrote inside the widget call.

Let’s perform this substitution exercise on each of the slots in your stripped-down minimal example:

Starting with the widget definition:

<$slot $name="ts-raw">Default</$slot>
<$slot $name="extra">Result</$slot>

Let’s first replace the ts-raw slot with what we know fills it (the contents of the widget call), that is,

	Bespoke
<$fill $name="extra">Custom</$fill>

Result:

	Bespoke
<$fill $name="extra">Custom</$fill>
<$slot $name="extra">Result</$slot>

Now let’s replace the extra slot with what fills it (Custom):

	Bespoke
<$fill $name="extra">Custom</$fill>
Custom

This is what the widget call actually evaluates to.

And if you copy and paste that into a tiddler, you get:

Bespoke Custom Custom

In fact, if you simply copy and paste <$fill $name="extra">Custom</$fill> into a separate new tiddler, it displays Custom. Apparently, the behavior of $fill widgets that aren’t contained in $transclude or widget calls, is to simply display its contents. (If that is a bug, then the simplest way to reproduce the bug is actually to just paste <$fill $name="extra">Custom</$fill> into a new tiddler. One could make an argument that this should display nothing, since there is no slot being filled. But because it displays its contents, it has the effect of “duplicating” the other slot, since it is explicitly filled separately.)

I’m sure you know the reason now, but for the sake of completeness: If you remove the ts-raw slot, then you’re not copying the $fill widget into the ts-raw slot, so you only see the Custom from the extra slot. Likewise, if you explicitly fill the ts-raw slot, then it is filled only with whatever you fill it with, but not with the whole contents of the widget call including the $fill widgets.

Thanks, @bluepenguindeveloper — now I understand what was going on, technically.

Still, I’m not sure how this behavior is beneficial. Would anyone want the ts-raw to include any named fill widgets, rather than whatever content is, well, “raw” within the widget?

As it is, I don’t see any way that I can use the ts-raw option (which seems to be the best way to work with complex “on-the-fly” content) AND also fill a named slot. And to get all that without the doubling.

So, although I see what you mean about the slot-fill becoming part of what ts-raw is working with, I’m still thinking that having a ts-raw slot would be more valuable if it could ignore fill widgets.

Or, am I missing some other trick so we can take advantage of a ts-raw slot AND fill in a value for a named slot — all while avoiding this duplication effect?

1 Like

I think you have a good point. Even if not a bug, it seems to be a bit of a design oversight.

One idea for the development of TW - and I was debating starting a separate topic to suggest this even before I saw your response - would be to enhance the fill widget to add an extra attribute ignoreIfNoSlot or ignoreIfNotInTransclude (gotta work on the attribute name) that would change the behavior of the fill widget to not display anything if not filling a slot in a widget/transclude. I suspect this would be considerably easier to accomplish than modifying the code for the ts-raw slot to ignore fill widgets. Plus, by using a new widget attribute rather than changing default behavior, any potential backwards compatibility issues with changing default behavior could be avoided (although I agree with you that it’s hard to imagine wanting it to behave the way it does, so it’s unlikely that there’s currently anything that relies on that behavior).

1 Like

Hi @Springer I can understand the confusion.

The ts-raw predefined fill name exists for the specific purpose of allowing a custom widget that delegates to another widget to be able to pass the entirety of the calling widget contents to the delegate. The “Visible Transclusions” demo in the core is an example of the technique.

Perhaps there could be a variant of “ts-raw” that would be useful for you?

1 Like

Perhaps!

On the other hand, I haven’t yet developed enough fluency with the powers of slot/fill widgets to be clear on what’s at stake for me in being able to use the ts-raw slot while also filling other named slots.

So, at this point, I’m happy to let this coast as a place where it seems there could be an improvement down the road. Let’s see if any other users also feel limited by the way a ts-raw slot interacts with adjacent fill widgets.