Here is a subtle mistake that I just spent hours debugging (finding, really). Maybe this will help someone not to repeat that.
When combining two conditions in a filter, I often used something like this:
<$list filter="[«condition1»] :all[«condition2»] :and[nth[2]]" variable="void">
The conditions were written such that they returned exactly one item when true (with e.g. a then[yes]
at the end) and nothing when false.
When both conditions were true, there would exist two input list items into the :and
prefixed filter run, so that nth[2]
returned the latter and the $list
content was rendered. Setting the variable to void avoids unintentionally messing with currentTiddler
(another mistake that I made often early on).
However, when «condition2»
is such that a title is returned, and that title changed, the above code would lead to the whole $list
content being destroyed and re-rendered, because the value of the filter
attribute has changed, even though the logical result that both conditions are true has not. Having something like this in a PageTemplate can lead to very weird navigational behavior.
Anyway, the solution is to simply count the number of items in the list like so:
<$list filter="[«condition1»] :all[«condition2»] :and[count[]match[2]]" variable="void">
where the match[]
parameter should match the number of conditions one wants to be true. As long as both conditions remain true, the filter output does not change and the $list
widget does not destroy or create any DOM elements.
Have a nice day
Yaisog
PS: The :all
filter run prefix prevents automatic de-duplication if both conditions return the same item, e.g. a yes
string, in which case match[2]
would erroneously not be true. Another mistake I’ve done before.
PPS: The same way one could also implement other logic (updated):
- NOR:
count[]match[0]
- OR:
count[]!match[0]
- XOR:
count[]match[1]
- XNOR:
count[]!match[1]
- AND:
count[]match[2]
- NAND:
count[]!match[2]