Help need to define a conditional parameter for a procedure

This is related to the post regarding usage of parameter widget in procedures.

Here I am testing usage of parameter widget in procedures.

Here is the code.

\procedure dyn-table-test()

<$parameters 

op-1="""<% if [{!!op-1-value}is[blank]] %> <<op-1>> <% elseif [<currentTiddler>!has[op-1-value]] %> <<op-1>> <% else %> {{!!op-1-value}} <% endif %>""" 

param-1={{!!param-1-value}} 

>

!!OP-1 ''<<op-1>>''
!!PARAM-1 ''<<param-1>>''

</$parameters>

\end

__First test__

<<dyn-table-test op-1:"note-subject" param-1:"rad">>

__Second test__

<<dyn-table-test op-1:"note" param-1:"tw">>

__Third test__

<<dyn-table-test>>

In the above code, I want the procedure to use parameter op-1 only if the op-1-value field of the currentTiddler is blank or if that field is not present. Otherwise it should use the fieldvalue op-1-value . I tried to define that condition here

<% if [<currentTiddler>get[op-1-value]is[blank]] %> 

<<op-1>> 

<% elseif [<currentTiddler>!has[op-1-value]] %> 

<<op-1>> 

<% else %>

{{!!op-1-value}} 

<% endif %>

but it is not working

I’m not following everything, but you seem to have a self-referring loop here.

It looks like you’re effectively making a circular reference here — specifying that the op-1 variable (parameter) should equal itself if op-1-value field is blank or doesn’t exist… (It seems [<currentTiddler!has[op-1-value]] would cover both of those, meanwhile.)

(Parameter definition can’t itself specify when that parameter should be used — it seems like you’re trying to get the op-1 parameter when to make itself active, but it can’t work like that…)

Ah, I see you have a demo/model linked.

Is this (below) what you wanted?

op-1="""<% if [<currentTiddler>!has[op-1-value]] %> {{!!op-1}} <% else %> {{!!op-1-value}} <% endif %>""" 

I think you wanted to specify {{!!op-1}} as field value, not as variable value <<op-1>>, in your parameters declaration.

I was trying to use this code you shared previously.
There I saw you have used version=<<version>>
I was trying to make that into a conditional parameter

Ah, that worked only because <<version>> is already a defined macro, if I recall the context.

There is a field called op-1-value . No op-1 field exist.
What i was trying is use the op-1-value if it is present in the tiddler, otherwise use the parameter value i have specified in the procedure call.

op-1 is a parameter I am defining using parameter widget.
op-1-value is the field present in the tiddler

So:

<$parameters 

param-1={{!!param-1-value}} 

op-1="""<% if [<currentTiddler>!has[op-1-value]] %> <<param-1>>  <% else %> {{!!op-1-value}} <% endif %>""" 

>

Like that?

Usually you can specify the parameter value in the procedure call, and the parameters widgets give you a fall-back.

Do you mean that you want the parameter to refuse to be overwritten by what you specify, in the event that the field value is present? Yet you do want to be able to call the procedure with parameters, even when these should be overridden (because the tiddler’s field value should “win”)?

If so, I think you need a third parameter, one that you will not be tempted to specify manually in the procedure call. That third parameter will look for [has[op-1-value]], retain that value if it’s available, and only then consider your op-1 as specified in the procedure call.

This is what I was trying to explain.

I am in the process of modifying a dynamic table procedure I created by adding parameter widget - here is an example.
Since I am only in the process of modifying it, I am not sure how it will work out eventually. I was just trying out various possibilities.

Can you show me how to do this ?

My first thought is that you generally want to use a filtered transclusion to define a parameter; anything in quotes will be treated as a literal string and not wikified before substitution (which I assume you want to happen). And you probably don’t need the <% if %> construction, since you can achieve the same thing with the :else/~ filter run prefix. So—focusing on the filter aspect only, since I don’t quite understand how you intended the apparent loop to resolve…

I’d try something like

variableName={{{ [<currentTiddler>get[op-1-value]] ~[<op-1>] }}}

Since you want to assign the same value both when !!op-1-value is blank and when it’s missing, it’s easier to begin with the unique case (when {{!!op-1-value}} has a non-blank value) and provide <<op-1>> as a fallback. You could alternatively use

[<currentTiddler>has[op-1-value]then{!!op-1-value}]
                  ^                       ^
tests for non-blank field      retrieves the value of the field

… but [<currentTiddler>get[op-1-value]] is more efficient, as get only returns the value of a non-blank field, by definition.

ETA: Or, slightly shorter, [{!!op-1-value}!is[blank]] ~[<op-1>] or [{!!op-1-value}!match[]] ~[<op-1>] would also work.

3 Likes

@arunnbabu81 Just A few suggestions in General, that would help your solution and our supporting it.

  • Don’t include empty lines where unnecessary, grouping code together to show where a procedure begins or ends helps see the structure.
    • Here I use the ; to allow the output at the bottom to be grouped as well.
  • Don’t use the %if, except at the last minute because it acts somewhat like widgets, which describe blocks to be displayed (%if/%else) or conditionally displayed.
    • All your %if is doing is using filters and outputting variables so these could all exist inside a filter or function, this is an unnecessary use of a code construct.
  • If the parameter value is complex like your op-1= move that value to a named procedure/function/macro rather than complicate the code as you have above.
    • As soon as I did this I was able to more easily see your code, And realised if the op-1-value has no value and op-1 parameter is not provided, it returns op-1 which is undefined.
"""<% if [{!!op-1-value}is[blank]] %> <<op-1>> <% elseif [<currentTiddler>!has[op-1-value]] %> <<op-1>> <% else %> {{!!op-1-value}} <% endif %>""" 
  • I would redefine this as a filter or function, I won’t here, unless you ask, because I think you are moving forward

Here is an example of how I would have presented the above;

\procedure dyn-table-test()
<$parameters op-1=<<new-function>> param-1={{!!param-1-value}}>

!!OP-1 ''<<op-1>>''
!!PARAM-1 ''<<param-1>>''
</$parameters>
\end dyn-table-test

\function new-function()
Replaces %if statement, to be coded
\end new-function

;__First test__
<<dyn-table-test op-1:"note-subject" param-1:"rad">>

;__Second test__
<<dyn-table-test op-1:"note" param-1:"tw">>

;__Third test__
<<dyn-table-test>>

This is not working code but a proposed better presentation

  • There is a blank line after the opening $parameters widget to force block mode.
1 Like

Thank you both @etardiff and @TW_Tones for your suggestions. It’s early morning here and I have to go to work. In my short testing in mobile, these suggestions are working when I defined a new variable with the code provided by @etardiff . Once I do my testing in my original dynamic table code, I will give a detailed feedback

@etardiff

I tried, but it was not working as I intended- here are the test tiddlers- 1 and 2

What I want is that

  1. if the field called op-1-value is present and is not blank, then I need the {{!!op-1-value}} to override the value assigned to the op-1 parameter in the procedure call.

  2. If the field op-1-value is absent or is blank, then the value assigned to op-1 parameter in the procedure call should be used.

Can you help ?

I think your problem is that, as @Springer pointed out, op-1={{{ [<currentTiddler>get[op-1-value]] ~[<op-1>] }}} creates a loop where <<op-1>> falls back to looking at itself rather than using the parameter you supplied in the macrocall.

I believe this produces your intended behavior:

\procedure dyn-table-test(op-1, param-1)
<$parameters 
	op={{{ [<currentTiddler>get[op-1-value]] ~[<op-1>] }}}
	param={{{ [<currentTiddler>get[param-1-value]] ~[<param-1>] }}}
>

	!!OP-1 ''<<op>>''
	!!PARAM-1 ''<<param>>''
</$parameters>
\end

__First test__
<<dyn-table-test op-1:"note-subject" param-1:"rad">>

__Second test__
<<dyn-table-test op-1:"note" param-1:"tw">>

(And if we’re offering code-formatting opinions, I vastly prefer to have each variable definition on its own line as you did in your original post—though I probably wouldn’t use quite as much space. :wink: )

3 Likes

Thank you @etardiff . That’s was just a small step in my journey. Still a long way to go before my dynamic table gets a functional parameters widget

Topic is marked solved, but I’m not sure whether the question you asked me was fully resolved…

\procedure dyn-table-test(op, op-now, param-1)
<$parameters
	op={{{ [<currentTiddler>get[op-1-value]else<op-now>] }}}
	param={{{ [<currentTiddler>get[param-1-value]else<param-1>] }}}
>

	!!OP ''<<op>>''
	!!PARAM-1 ''<<param>>''
</$parameters>
\end

__First test__
<<dyn-table-test op-now:"note-subject" param-1:"rad">>

__Second test__
<<dyn-table-test op-now:"note" param-1:"tw">>

__Third test__
<<dyn-table-test>>

If I understand your requirements, there’s this odd feature: you want to be able to specify something like an “op value” in the procedure call BUT you don’t want that value to actually do anything unless there’s no op-1-value specified within the tiddler’s op-1-value field. Is that right? And you don’t seem to have anything like a hard-coded default value. So I’ve made op-now the parameter that you can specify directly. If you do, it still won’t be used, unless there’s no op-1-value available. However, it also means that if the field is empty and nothing is specified for op-now within the procedure call, there’s no value at all for that part.

In other words: Whenever you actually have values in those fields, whatever you’re specifying “ad hoc” within the procedure call is irrelevant. Was that what you were aiming for?

Thank you @Springer for taking your time to solve this…I think your solution is almost similar to the one by @etardiff which was working as I intended.

If you experiment with the dynamic table I shared in one of my previous post, you may understand what I am trying to achieve. Currently my dynamic table will show the entry after I build the filter steps using multiple select widgets which assign value to different tiddler fields (corresponding to each filter steps).
I want to add another dimension to the dynamic table procedure call…that is to use the parameters widget to assign values to parameters corresponding to these filter steps…and directly use these parameters during the procedure call instead of using select widget to assign field values

It’s little complicated. But I hope to make it working soon.

Edit: Here is the dynamic table demo

Click on this image on the left top to change the filter
Click on these buttons image to change the view mode