I want a filter that normally puts the new item as last in the list… but puts it in the first place of the list if it was already present in the list.
Do you have an elegant way to do this?
Hi @JanJo ,
Here is one way to do this :
\define newitem() foo
<$button>go
<$action-listops $subfilter="[all[]] :filter[all[]match<newitem>] :then[prepend<newitem>] :else[append<newitem>]"/>
</$button>
I like to put explicit [all[]]
s in subfilters so that I better see what action-listops actually works on. The trick in the filter above is to also use this whole initial list inside the :filter[]
to test whether the item already belongs to it: if this is not the case, the result of the :filter[]
run is empty, so the item is appended to the list.
The only problem I just encountered is that it prepended the item without removing it first, so that it had a double appearance.
Even worse: my attempt just doesn’t work when new items contain spaces. Right now I can’t figure which operators could be used instead of append and prepend.
Hopefully a good soul comes up with a real solution
Give this a try:
item=<$edit-text field="item"/>
list=<$edit-text field="list"/>
<$let item={{!!item}}>
<$button>add item
<$action-listops $subfilter="
:filter[match<item>]
:then[insertafter<item>putfirst[]]
:else[insertafter<item>]"/>
</$button>
<$button>delete item<$action-listops $subfilter="-[<item>]"/></$button>
Notes:
-
insertafter<item>
always puts the<item>
at the end of the list. -
putfirst[]
then moves the last item to the start of the list
edits:
- I removed the
[all[]]
filter operators, as they are not needed. The$action-listops
widget’s$subfilter
param always starts with the current field content, and the:filter
filter run operator is applied to each input item. - I also added
$edit-list
widgets to enter the item to be added and manually edit the current list field as well as a “delete item” button to make it easier to experiment with different values.
enjoy,
-e