How can you conditionally add filter runs?

Hi everyone. I would massively appreciate some help on this problem.

I have a function that returns a list of tiddlers, that I will use within a list widget in a view template. It is something like this:

[function[my_tiddler_list]]

Now I want to do a bit more filtering, but only under certain conditions. Specifically if the current tiddler is not called Stuff I want the filter to look like this:

[function[my_tiddler_list]] +[tag<currentTiddler>]

Otherwise if the current tiddler is called Stuff I want the filter to look like this:

[function[my_tiddler_list]] -[tag[Activity]tagging[]]

I’m struggling to find a good pattern for applying these extra filter runs only under certain conditions.

The below is my best attempt. It works for the first condition, but not the second.

\function conditional_run()
[<currentTiddler>!match[Stuff]] :then[tag<currentTiddler>] :else[remove<all_tagged>]
\end

\function all_tagged()
[tag[Activity]tagging[]]
\end

<$list filter="[function[my_tiddler_list] +[function[conditional_run]]" />

Can anyone help? :slight_smile:

Quick idea, I have not tested it:

Create two functions, where each one constructs the final expected list under a given condition, lets say .function-if-stuff[] and .function-if-not-stuff[].

Use one or another based on the condition, e.g.
[<currentTiddler>match[Stuff]] :map:flat[.function-if-stuff[]] :else[.function-if-not-stuff[]]

If current tiddler is stuff, then map:flat returns all results of function-if-stuff. If not, the first two filter steps will produce no output, and the third :else step will kick in.

This will only work for the simple example with one binary condition that you gave, it would be difficult to reliably adapt to work with a more complex logic.

1 Like

This is exactly the kind of situation where the new <% if %> shortcut syntax makes things easy to compile in a semantically natural way:

<% if [<currentTiddler>!match[Stuff]] %>
{{{  [function[my_tiddler_list]] +[tag<currentTiddler>] }}}
<% else %>
{{{  [function[my_tiddler_list]] -[tag[Activity]tagging[]] }}}
<% endif %>

Is there some reason your view template can’t work with this syntax, and you want to bundle it all into a more complex single function?

2 Likes

You can always write your own filter operator using JS

See how many filter operators I have written just to satisify my visualization desire…

1 Like

@vilc If I’m understanding you this is quite similar to my attempted solution. The problem I had was getting .function-if-stuff to do the equivalent of -[tag[Activity]tagging[].

@Springer This was my original approach (though using the list widget). The reason for trying to get a single filter expression was that I use the output of the same filter to make a few other decisions elsewhere in the template, and I’m trying to avoid duplicating code. Having said this I rewrote it using the <% if %> syntax and it is now tidy enough that I’m happy with it. Thank you!

@linonetwo Yes always an option - but I need to learn javascript first!

Thank you everyone for your help :slight_smile:

And interesting observation here is they new %if syntax promotes the use of more than one filter to represent logic patterns.

I would point out this is perfectly acceptable and easier to read than the long running trend to try and stuff everything into a single filter. There are plenty of cases where people are doing filter gymnastics to solve a problem in a single filter, when if multiple filters were used, such as in nested list widgets, it would be easier and more adaptable.

So hopefully this new syntax will reverse this fad.