I was curious about how to get this done. If you want to see how I managed it, you can expand the following. If not, I won’t be offended. It is a combination of many ideas discussed in this thread, with my own input plus that of @etardiff and @Springer
Scott's version
Here is an alternate version of your tiddler:
Doc Package Check Alternate.json (1.9 KB)
You can download this and drag the resulting file onto your wiki. It’s got a new name and shouldn’t overlay anything. It’s also self-contained; there are no changes elsewhere.
I made a number of changes:
Inlined variables
This was actually my last step after everything else was working. Your version has
<$vars ProgramInput={{$:/state/myProgramInput!!text}}>
<$vars PackageInput={{$:/state/myPackageInput!!text}}>
<$vars PMIInput={{$:/state/myPMIInput!!text}}>
</$vars>
</$vars>
</$vars>
First of all these could probably be better handled with a single LetWidget. But I found that point moot, because at the end I only used each variable once. To me that means that the only reason for declaring these variables is if it makes the code more understandable. That happens often enough, but here, I found that it was more understandable to replace <ProgramInput> in the filter with {$:/state/myProgramInput!!text} And because text is the default field, we can skip that and just use {$:/state/myProgramInput}. This is a choice that I tend to make, but there is absolutely no objection if you still prefer the variables.
Selection logic for PMI
The reason for your question was to handle the additional complexities in document selection. Here’s my current understanding of the special rules: If the Program selection is Fixed, then a document that has PMI: x is included only if the PMI dropdown is Yes. If the PMI dropdown is No, then it should not be included. However, if the Program selection is something other than Fixed, then a document with PMI: x is included regardless of the value of the PMI dropdown.
This seems to affect only one document in the list (Worst Case Amortization Schedule)Doc Package Check Alternate.json (1.9 KB)
, but that doesn’t matter to the logic.
Here’s how I handled it:
<$let maybePMI={{{
[{$:/state/myProgramInput}match[Fixed]]
:then[has:field[Fixed]!PMI{$:/state/myPMIInput}]
}}} >
<$list filter="""
[tag[Documents]has:field{$:/state/myProgramInput}has:field{$:/state/myPackageInput}]
-[<maybePMI>]
+[sortby<stackwise>]
""" variable="tiddler">
<tr> <!-- ... --> </tr>
</$list>
</$let>
We’ll discuss the sort bit below.
What we want to do is to include all potentially relevant documents, then remove Worst Case if it meets our somewhat complex condition. However, to handle that complex condition, the only way I found was to use two filter runs, and the filter syntax doesn’t have any parentheses to group those two runs. So I define it ahead of time as a variable. (maybePMI. You might have a more appropriate name; I called it foo until I came to write up this post, because I didn’t have a name for it.) The way that definition works is based on the realization I mentioned in a previous post, corrected by @etardiff’s explanations: We test if the current ProgramInput is Fixed in one filter run, and in the next one, we use the filter prefix :then to select the tiddler we want to remove.
Then in the filter for the <$list>, we select all potentially relevant documents and remove the oddball one. You’ll notice that we don’t use stack in here. That’s coming up next.
I split the filters for both the <$let> and the <$list across multiple lines. And when I did so, I replaced the one double-quote for my attribute with triple double-quotes (""".) I don’t know if others do the same thing, but I used the triple quotes with multiple lines just as a visible reminder that the attribute goes across multiple lines. This could be plain double-quotes, and it could all be on one line; your choice.
Finally, there is a bug in here. It only works completely correctly because there is only one document to remove. We might be able to patch this up with <$set> in place of <$let>, and possibly some enlisting, but I won’t try that. @etardiff made useful suggestions before. Perhaps she can offer clean-up here.
Sorting
The biggest structural change was offered by @Springer. The original mechanism was awkward: We iterated through all the stacks, and reran our filters each time, including also a test for matching the current stack. It would be much cleaner to select the right tiddlers and then run a sort on the result.
I was trying another approach for the sorting than what @Springer suggested. I thought @etardiff’s indexof was gong to be enough, or my version of the same, but I never did manage to get that version working properly. However, the version from @Springer works perfectly.
Instead of her suggestion of putting our sorter in a $:/tags/Global context, I just use it locally. If you need it in multiple places, then do move it to a global location.
All that was necessary was to wrap the contents inside a a
<$set name="stackwise" filter="[{StackingOrder}enlist-input[]listed[stack]is[tiddler]]">
<!-- contents here -->
</$set>
and to sort the filtered document tiddlers with
+[sortby<stackwise>]
If that sorter is not clear enough, please ask. I’m sure @Springer could explain. Or I could, although it took me a few minutes at first to understand. I still want an indexof one working correctly though. Perhaps one day.