How can I search for empty field values without knowing the field name?

Greetings! First time poster - hopefully this is in the right place.

Here’s a tiddler that almost does exactly what I want.

<$set name="destination" value=<<currentTiddler>>>
<$list filter="[is[current]fields[]]+[tag[Skills]]+[sort[]]">
        {{!!tt}} <$view tiddler=<<destination>> field={{!!title}}/>, &nbsp;
</$list>
</$set>

The list-widget’s filter looks for all the field names, then select only those field names where there are tiddlers which have been tagged “Skills”. and then sorts everything.

It works great, however, it also displays fields that exist in which the field’s value is blank or empty. I don’t want that. I’d like to only show results where there is an actual value in the field.

Normally I would just check the field itself for a value, like this: !field:skills[] where I’m saying ‘don’t show me anything where the field is empty’. Yet in this case, I can’t do that because the fields I’m checking are dynamic (based on which tiddlers are tagged with ‘Skills’).

Any help, thoughts, ideas would be much appreciated and have my thanks!

Does [is[current]fields[]] :filter[<..currentTiddler>has<currentTiddler>] +[tag[Skills]] +[sort[]] work for you? By default, has will ignore empty fields.

2 Likes

EPIC WIN!

To be forthcoming, I’m not exactly sure how that middle part ( :filter[<..currentTiddler>has<currentTiddler>] ) works - yet it works flawlessly!!

Tell your boss you deserve a raise! You have my thanks, Dear Friend!

1 Like

Let’s break it down, then:

  • This filter run uses the confusingly-named “filter” filter run prefix. Like its cousin, the “filter” operator (used inside a filter run, typically with another filter stored as the <variable> or {!!field-transclusion} parameter of the filter operator), :filter will pass its inputs, unchanged, if those inputs produce any output when run through the filter following :filter.
    • Has the word “filter” lost all meaning for you too? :wink: Let’s look at a simpler example: [<currentTiddler>] :filter[get[caption]].
      • Here, the :filter run’s input is <<currentTiddler>>. This is the starting value for the run — think of it as equivalent to :filter[<currentTiddler>get[caption]].
      • As usual, get retrieves any non-blank value of the caption field.
        • [<currentTiddler>get[caption]] would output the value of the caption field.
        • However, since we’re using :filter, the specific output of this run is discarded. Instead, since [<currentTiddler> ... get[caption]] produced a value, <<currentTiddler>> gets passed on to the next step of your filter (if applicable), or listed among the final outputs.
  • Inside a :filter run, we have access to some special variable definitions:
    • <currentTiddler> = the input value being processed by the :filter run.
      • In your case, that is each field name in use on the current tiddler.
    • <..currentTiddler> = the original value of <<currentTiddler>> outside this filter run.
      • In your case, that’s the tiddler whose fields you’re examining.
  • Thus, in plain language, [is[current]fields[]] :filter[<..currentTiddler>has<currentTiddler>] means, “If this tiddler has a non-blank value for a given field, pass the name of that field on the next step of this filter.”

Hope that makes sense! Let me know if you have further questions.

3 Likes