Filter to say (A AND (B OR C))

In an edit template, I wanted to use a filter that says if the current tiddler has either field A or field B. This is akin to (A AND (B OR C)). So I started from:

<$list filter="[all[current][[has:field[first-met-on]] [has:field[last-met-on]]]]">

and umpteen permutations of that and went into a whirl of square brackets going all over the place. But could not get it right.

What is the correct way of writing this?

On a related note, are the following two just the same?

<$list filter="[all[current]tag[Contact]]">
<$list filter="<currentTiddler>tag[Contact]">

In an edit template, I wanted to use a filter that says if the current tiddler has either field A or field B. This is akin to (A AND (B OR C)). So I started from:

<$list filter="[all[current][[has:field[first-met-on]] [has:field[last-met-on]]]]">

What is the correct way of writing this?

Using De Morgan's laws - Wikipedia, we can convert (A AND (B OR C)) into (A AND B) OR (A AND C). So, we can write your filter as two filter runs: <$list filter="[<currentTiddler>has:field[first-met-on]] [<currentTiddler>has:field[last-met-on]]">

However, this is not quite enough, as this could potentially fulfill BOTH conditions, which would result in the $list contents being rendered twice. To address this, we can add +[limit[1]] to the end of the filter.

Thus, this is the general filter pattern for invoking an OR conditional:

<$list filter="[<currentTiddler>has:field[first-met-on]]
               [<currentTiddler>has:field[last-met-on]]">
              +[limit[1]]">

On a related note, are the following two just the same?

<$list filter="[all[current]tag[Contact]]">
<$list filter="[<currentTiddler>tag[Contact]]">

Yes, they are logically equivalent. (Note: you left off the outer brackets in the second line… I fixed it.)

Potentially the only difference is one of performance. Both forms of syntax perform a variable lookup, which is highly optimized in the TWCore JS code.

<currentTiddler> is slightly more direct, in that it immediately invokes options.widget.getVariable(title) (see $:/core/modules/filters/getvariable.js).

In contrast, [all[current]] does do slightly more processing to handle a variety of other possible use-cases such as [all[tiddlers+shadows]] or [all[missing]] (see $:/core/modules/filters/all.js and $:/core/modules/filters/all/current.js). Ultimately, however, [all[current]] also invokes options.widget.getVariable("currentTiddler") to actually get the current tiddler’s title.

You should use whichever syntax makes conceptual sense to you. I personally prefer [<currentTiddler>...].

enjoy,
-e

7 Likes

@EricShulman Thanks. Your solution worked perfectly. And the mention of De Morgan’s Laws reminded me of the college days. :slight_smile: