Complex Indirect Filter Help

I’m developing a plugin but encountered an issue. It’s a task management-related plugin where some entries are projects with a field tmo_projectFilter whose value is a filter expression. This allows users to display tasks from two projects within a single project. I then created a panel that filters out entries with the tmo_projectFilter field and further checks if the filter value includes incomplete tasks. If there are incomplete tasks, the project is needed; if not, it shouldn’t be displayed. Here’s the code I wrote, but it didn’t achieve the desired result.

<$list filter="[all[tiddlers]tmo[Project]tmo_projectState[doing]] :filter[subfilter{!!tmo_projectFilter}tmo_taskState[todo]count[]!match[0]]">  

!!! <$link><<currentTiddler>></$link>  

</$list>  

I’ve tried various filters and prefixes, but none of them have yielded the results I’m looking for. Thanks in advance.

Added, the value of the tmo_projectFilter field is usually [tag<currentTiddler>], which can lead to some variable passing issues.

I’ve made some attempts before. The code below filters in two passes, but there is a problem with the presentation logic. For example, when there are no qualified task entries in the filter for which a tmo_projectFilter value exists, it is displayed as empty. If I add a blank display template, then several blank templates may be displayed.

<$list
  filter="[all[tiddlers]tmo[Project]tmo_projectState[doing]]"
>
  <$list-template>
  <%if [subfilter{!!tmo_projectFilter}tmo_taskState[todo]count[]!match[0]] %>
    <dl>
    <dt class="TH-project">
    <$link to={{!!title}}><$view field="title"/></$link> {{||$:/plugins/mabuqian/TaskHub/images/pie}}
    </dt>
    <dd>
    <$list filter="[subfilter{!!tmo_projectFilter}tmo_taskState[todo]]" template="$:/plugins/mabuqian/TaskHub/ui/todo/TodoItem"></$list>
    </dd>
    </dl>
    <%endif%>
  </$list-template>
  <$list-empty>
    {{$:/plugins/mabuqian/TaskHub/ui/welcome/EmptyNextActions}}
  </$list-empty>
</$list>
1 Like

It would be helpful if you could say something clearer than “I’m not getting the results I’m looking for”.

What are you getting, and why is that surprising / how does it differ from what you expected?

General troubleshooting: make the filter simpler, see if you’re getting the results you need in those simpler versions, so you can isolate the filter step where things seem to be going wrong.

While troubleshooting, also try hard-coding your filtered list (using titles instead of <currentTiddler> references) in the left-hand pane of a tiddler with the relevant fields, so that you can toggle the preview pane into view and troubleshoot results much more quickly than you can by editing your view template, and then checking to see how it displays within the relevant tiddlers.

One small specific tip (without lots of time to follow your details): The code in your first post boils down to:

<$list filter="[tmo[Project]tmo_projectState[doing]] :filter[subfilter{!!tmo_projectFilter}tmo_taskState[todo]count[]!match[0]]"/>

  • You don’t strictly need the all[tiddlers] initial step if your filter starts with myfield[desiredvalue] structure.

  • <$link/> would be enough to get the effect of <$link><<currentTiddler>></$link>. And just closing the <$list> widget after the filter with /> is enough to show you the default list of linked titles (= <$link/> for each) as the result… As long as you’re still troubleshooting the output of a filter, the simple <$list ... /> is the easiest thing to work with.

Sorry for the late reply. Let me explain. The code in the first post is what I used for my own testing. The code in the second post is from my plugin. But Though the issue may be less important than just displaying a blank space on the page. It doesn’t really affect much. But I do wonder what the filter would do to fix this. I’ve been trying to figure it out for two or three nights in a row now, and I’ve scoured the forum posts and still haven’t found an answer.

Let me describe the problem in more detail next. Firstly I have some project entries that have fields as shown in the code below.

created: 20250618172550631
description: 
modified: 20250618201040817
tags: 
title: 789
tmo: Project
tmo_projectFilter: [tag<currentTiddler>]
tmo_projectState: doing
type: text/vnd.tiddlywiki

The key is the tmo_projectFilter field value, which is a filter that may contain variables and by default contains the currentTiddler variable.

Then I have some task entries as shown in the code below. This entry has a label, which is not mandatory, it just does it by default. There are several similar entries. The field tmo_taskState in there can usually be divided into two categories, those that are todo and those that are not. it’s easy to tell.

created: 20250620191840642
modified: 20250620191845045
tags: 789
title: 66
tmo: Task
tmo_dueDate: 
tmo_taskState: done
type: text/vnd.tiddlywiki

Now the real problem arises. I need to filter a series of project entries and parse the tmo_projectFilter filter within them. If the number of task entries filtered by this filter where the value of the field tmo_taskState is “todo” is not zero, then this project needs to be displayed; otherwise, it does not. If none of the project entries have task entries with tmo_taskState value “todo”, I need to provide a blank template. This is what I want.

The problem I’m currently having is that I’m splitting this filter into two parts. If I use a blank template in the second part, then there is an issue where an item that has subtasks with todo is displayed. The other project has no sub-tasks for todo and will show up as a blank template. A third project also has no subtasks for todo and will also show the blank template. This displays two blank templates. And this is not what I was expecting. The current example sets the blank template to blank in the second filter section. This results in that if all of the items do not have subtasks for todo, then only blanks are displayed, not a specific blank template entry as I would expect.

I haven’t researched new features like functions enough. I think my experience with TiddlyWiki is okay, but I still can’t solve this problem. I’m sure TiddlyWiki’s powerful filters could solve this, but perhaps there are some very technical issues here. Another possible solution would be to write a filter expression via js that handles it specifically, and that’s beyond my capabilities.

Hopefully this explains it all, and any discussion and attempts to solve this problem are welcome.

Do you have a demo wiki you could share? I’m not sure this is fundamentally a difficult problem, but it’s a bit difficult to follow (and test) in the abstract. If you could upload an anonymized version that includes all the relevant templates, I think it’d be much easier to help you.

If you don’t already have a preferred web host, I recommend tiddlyhost.com!

Sorry for the late reply. You can find the repository and test URLs in the following URLs. Please ignore the repository name, that was the name of one of my previous plugins.

I created four projects, two of which do not currently have subtasks for todo. The other two projects have subtasks. They are shown in the image below. I want when all four tasks in the image are ticked and completed, then a specific template will be shown.What I can achieve now is to either show a blank template four times or nothing at all.

The exact code can be viewed in the plugin entry content. You can jump over to it via the link symbol above the tabs.

The key issue here is the double judgement, one judgement is if there are no more open subtasks for all ongoing projects, if so then a blank template is shown. If not, then a specific template is shown for projects with subtasks. Inside requires the use of subfilter filters for referenced field values.

Feel free to continue the discussion and reply.

Thanks for the explanations and example wiki!

Looks like this filter achieves the desired result:

[tmo[Project]tmo_projectState[doing]] :filter[all[tiddlers]subfilter{!!tmo_projectFilter}tmo_taskState[todo]count[]!match[0]]

I added all[tiddlers] at the beginning of the :filter run, because otherwise the run starts with an empty input. :filter runs don’t have an implied all[tiddlers] input when their first operator isn’t a selection constructor.

I guess you could use something more restrictive than all[tiddlers], tmo[task] for example, but it would probably not lead to a big performance boost in this case, as your tmo field is not indexed by the core.

Hope this helps,

Fred

1 Like

Holy shit, you did it. You actually did it. It’s unbelievable.

I always thought I had a pretty good grasp of the filter, but it took me three days to figure it out. This. This. I didn’t think the answer would be this. It left me with mixed feelings of failure and happiness. The sense of failure came from the fact that three days of my time had been wasted, and that this was something I should have had to think of a long time ago. And This is too Happiness comes from the fact that this problem can really be solved, and that TiddlyWiki is still powerful. It’s just that the filter expression I was anticipating should be much more complicated than this.

Thank you so very, very, very much.

2 Likes