Why is the action setfield widget keep on modifying the fields in the same way

https://demo-hub.tiddlyhost.com/#test

In this tiddler there is an update button. On pressing it, a variable defined by the let widget is added to a particular tiddler field using action setfield widget sequentially. But I want this to happen only once. Any idea why this sequential behavior happens ?

I don’t really follow what you mean by “sequentially”. The button seems to do what you’re telling it to do.

There are strange features of your code though:

comb-tbl-filter variable relies (indirectly) on tbl-filter variable, which in turn pulls from the field tbl-filter-value.

So when you set that field to the current value of comb-tbl-filter, the variable comb-tbl-filter is now changed to a much longer string (and each time you use the button action, the field is bloating with the recursive inclusion).

1 Like

Why wouldn’t it? You don’t have any filters to prevent it being applied more than once.

Here’s the kind of fix I’d try:

In your $let widget:

add-filter=`search:$(tbl-search-field-list-join)$:$(tbl-search-flag-list-join)$[$(tbl-search-param)$]limit[$(tid-limit)$]!prefix[$:/state/]]`
comb-tbl-filter=`$(tbl-filter-minus-closing-bracket)$$(add-filter)$`

Inside your button:

<$button tooltip="update procedure paramter to filter steps">
<% if [{!!tbl-filter-value}!search:title:literal<add-filter>] %>
<$action-setfield $tiddler=<<currentTiddler>> tbl-filter-value=<<comb-tbl-filter>> $timestamp="yes"/>
<% endif %>
Update 2
</$button>

The <% if %> will look for the additional string that would otherwise be added by the button and apply the action widget only if that (literal) string is not already present in the field.

https://demo-hub.tiddlyhost.com/#%24%3A%2Farsheth%2Fdyn-table%2Fprocedure

In this dynamic table procedure code, I use a similar method and it was working (line nunmbers 147-150 and 175-217). Can you tell what is the difference here ?

I’m sorry, that’s far too much dense code for me to dig through. I’d recommend extracting the relevant sections only (omitting any code that’s not directly related to your question) to paste here, and I can take another look. Or you may discover the difference yourself in the process of preparing your examples—I often do. :slight_smile:

I support @etardiff request here, when you ask a question you are asking someone to help, even reading takes effort.

We should do what we can to reduce this effort otherwise we are asking too much of others who give their time freely to help.

<$let tid-limit={{!!tbl-tid-limit}}}
op-1={{!!op-1-value}} 
param-1={{!!param-1-value}} 
tbl-search-param={{!!tbl-search-param-value}}
tbl-search-field-list={{!!tbl-search-field-list-value}}
tbl-search-field-list-join={{{ [<tbl-search-field-list>split[ ]join[,]] }}}
tbl-search-flag-list={{!!tbl-search-flag-list-value}}
tbl-search-flag-list-join={{{ [<tbl-search-flag-list>split[ ]join[,]] }}}
filter1=`[$(op-1)$[$(param-1)$]search:$(tbl-search-field-list-join)$:$(tbl-search-flag-list-join)$[$(tbl-search-param)$]limit[$(tid-limit)$]!prefix[$:/state/]]`
>
<$list filter="[<currentTiddler>row-number[1]]">
<$button>
<$action-setfield $tiddler=<<currentTiddler>> tbl-filter-value=<<filter1>> $timestamp="no">
Update
</$button>
</$list>

Sorry for not responding early. It was sleep time here.
I gave the line numbers thinking that code mirror plus is installed in the demo wiki which it was not.

Above given is a bare minimum sample code from the procedure code

Okay, in both cases you’re using $action-setfield to set a field to the value of a variable, so let’s look at the variable.

[$(op-1)$[$(param-1)$]search:$(tbl-search-field-list-join)$:$(tbl-search-flag-list-join)$[$(tbl-search-param)$]limit[$(tid-limit)$]!prefix[$:/state/]]

Personally, I find it pretty hard to parse so many substitution variables in a row, so I replaced the ones you’re using as filter parameters with their corresponding <variable> forms:

[$(op-1)$<param-1>search:$(tbl-search-field-list-join)$:$(tbl-search-flag-list-join)$<tbl-search-param>limit<tid-limit>!prefix[$:/state/]]

That’s better, but still hard to read at a glance. Let’s replace the operators with some appropriate stand-ins:

[tag<param-1>search:title,tags:casesensitive<tbl-search-param>limit<tid-limit>!prefix[$:/state/]]

Now we can compare this a bit more easily to the filter that wasn’t working as expected:

tbl_filter=[note[rad]]
tbl-filter={{{ [<currentTiddler>get[tbl-filter-value]] ~[<tbl_filter>] }}}
tbl-filter-minus-closing-bracket={{{ [<tbl-filter>removesuffix<closing-bracket>] }}}
comb-tbl-filter=`$(tbl-filter-minus-closing-bracket)$search:$(tbl-search-field-list-join)$:$(tbl-search-flag-list-join)$[$(tbl-search-param)$]limit[$(tid-limit)$]!prefix[$:/state/]]`

You have a lot of indirection going on here, but what I notice immediately is that your combined filter <<comb-tbl-filter>> incorporates <<tbl-filter>>… which, if you have clicked the button at least once, will always be the current value of the tbl-filter-value field—which is the same field your button is modifying.

  • This means that each time you click the button, it retrieves the current field value and then adds the new filter components (which might already be present in the field).
  • Your properly-functioning filter doesn’t have this problem because it’s not starting from the target field’s current value, it’s just constructing a filter and then saving that filter to the field. It doesn’t matter what’s already in the field, because it will be overwritten anyway.

Assuming you want to be able to include ad hoc “starting” filters, here’s what I’d try:

\procedure update-filter() <$action-setfield $tiddler=<<currentTiddler>> tbl-filter-value=<<comb-tbl-filter>> $timestamp="yes"/>

<$let
	tbl_filter="[note[rad]]"
	starting-filter={{{ [<currentTiddler>get[tbl-start-filter]] ~[<tbl_filter>] }}}

	limit={{{ [<currentTiddler>get[tbl-tid-limit]] ~[<tid_limit>] }}}
	search-term={{!!tbl-search-param-value}}
	search-fields={{{ [{!!tbl-search-field-list-value}split[ ]join[,]] }}}
	search-flags={{{ [{!!tbl-search-flag-list-value}split[ ]join[,]] }}}

	rb="]"
	start-with={{{ [<starting-filter>removesuffix<rb>] }}}

	comb-tbl-filter=`$(start-with)$search:$(search-fields)$:$(search-flags)$[$(search-term)$]limit[$(limit)$]!prefix[$:/state/]]`
>

<<starting-filter>>
<<comb-tbl-filter>>

<$button actions=<<update-filter>> tooltip="update filter steps">
	Update
</$button>

I’ve taken the liberty of replacing some of your variable names with ones that were shorter and easier for me to parse, but the overall structure is pretty similar. The key difference is that I am storing what I’m calling the “starting filter” in a separate field, tbl-start-filter. This means…

  1. It’s easier to edit this part of the filter, independent of the long combined filter, and
  2. You don’t get into loops trying to modify tbl-filter-value based on itself, and you don’t need my hacky <% if %> workaround to disable the button when it shouldn’t be used.

Hope this helps!

1 Like

Thank you @etardiff for detailed explanations. It will take some time for me to comprehend everything. I will get back after testing it out.

Should I change those working codes. I settled for those may be because something else which I tried was not working. That was a huge project and it took me many weeks of thinking and reading to come up with a working dynamic table.

My coding style may not be ideal and correct, but all those are self learned things from the tiddlywiki.com or forum or other peoples projects, so there will be mistakes inevitably.

For the “real” variable you’re using to build your final filter, I think it’s fine to use the substitution variables—and you can see I did the same thing in my suggested code. I just found it helpful to replace the $(long-multiword-variables)$ with some more familiar-looking filter syntax to give myself a general idea of what was going on (and hopefully make the comparison between the filters more obvious to you, too).

1 Like