Token Box question

Hi,
probably an easy point I am missing, but I am trying to use @david.wylie’s excellent Multi Select drop down with Token-box component and I can’t find, in the page and in the example, how to retrieve the list of selected elements.

self.multi_select_drop_down.items

returns the Drop-down elements list and

self.multi_select_drop_down.token_box

doesn’t seem to have its own list property.
Must be easy but I can’t see it…

Thanks!

Off the top of my head, you will need to loop through the components of the box. I’m not able to check the code precisely, but from memory -

# pseudo-code, not checked.
for c in self.multi_select_drop_down.token_box.get_components():
  if type(c) is Button:
    # This is one of your selected items in the list.

edit - I tend to use the “tag” property to store useful data when creating these items, for example the dB id. That way the displayed text doesn’t have to be the only reference to what you selected.

1 Like

Thanks @david.wylie
I tried to follow your suggestion but I ended up with a slightly modified verison of your wonderful components, I share it here:
https://anvil.works/build#clone:QEB7GHBAT7MXF2D7=KOKBGJ6L4PTGIQBT2Y57MBOK
These the modifications:

TokenBox
This now exposes tokens_list property, a string list that returns the text of the tokens currently in the token box. It can also be set ad design-time to pre-set the contents of the token box, or at run-time to change it bulk.
I also substituted the callbacks with events x_element_added and x_element_removed, I find them easier to manage and propagate and in general more aligned to my mind. These events are fired whenever an item is added to or removed from the token box, with the elements name as text parameter. It doesn’t fire when elements are set assigning with tokens_list,

MultiSelectDropDown
Similarly to TokenBox, this now exposes selected_items both at design-time and run-time.
I also added the events x_element_selected and x_element_deselected with the element name as text parameter. It doesn’t fire when selected_items is assigned.

Here’s a usage example:
https://anvil.works/build#clone:NNPJIAQUUBOPSV7X=KJ254GY2Y5M52X3YXDL4HTMC

The RawTokenBox component should not be directly used.
When I modified David’s original TokenBox component, I had an odd behaviour in component’s initialisation (I can give detail if you’re curious), so I had to wrap it inside a flowpanel, through the separate TokenBox component.

5 Likes

I think this new version should replace David’s original in the library. @bridget

1 Like

With my blessing (not that you need it).

My components were only ever meant to be proof of concept. I always hoped others would improve on them. I think Shaun improved my original POC, even though my name remains on the credits.

1 Like

Thanx for this solution ! Struggled to find the selected items and then when I saw this post and added Aldos part I nailed it and it works fine now !

2 Likes

Many thanks to @david.wylie and @aldo.ercolani for all the work!

I needed a version of this to manage one-to-many relationships and was able to create one that’s working well (shared below with custom components and example).

The structure remains the same, but with slightly edited component names (RawItemBox, ItemBox, and MultiSelectItemDropDown). I’m not sure about the use case for setting anything directly in the ItemBox.

Usage/Properties

items: In essence the same as Anvil stock dropdowns, items must be set to a list of tuples with the first half of the tuple being the text to display, and the second half being the actual row to be used in the “many” part of the relationship (as in https://anvil.works/docs/how-to/dropdowns-data-tables). This needs to be the complete list of items available for selection, typically the result of a search() on the data table on the “many” side of the relationship.

selected_items: same as items, this must be formatted as a list of tuples built from the “many” side of the relationship, with the first half of the tuple being the text to display, and the second half being the actual row, but only those items that are actually currently related, can be an empty list, or can be set to None, if empty. Always returns current selected items or None.

placeholder: changed to a new default of ‘Select to add…’, I really don’t think going without a placeholder makes sense is this scenario, but I haven’t tested it with a blank one.

display_column: this must be set to the name of the data table column used in the first half of the tuple for items and selected_items.

edit_mode: boolean that enables use of the same custom component for both displaying the selected items and editing the relationship, can be toggled live to switch modes, selected_items works regardless.

show_none: boolean that, if true, will show a token with “None” when there are no existing relationships on the “many” side.

Notes

  1. This probably won’t scale well to a huge number of rows available on the “many” side, if I get into such a usage case, and work through both whatever performance issues arise, as well as displaying a search option at some configurable number of records, I will come back and share my updated components.

Enjoy!

https://anvil.works/build#clone:HSPPKNFRC3IZQPDX=KAH4ZOBRPFTBBRW7UHZ5GQS3

Updates

  • 5/12/2020
    • Changed selected_items to return None when there are no items selected (was returning an empty array.
    • Fix issue with setting selected_items to [] after use
  • 5/13/2020
    • Support setting selected_items to None

Plans

  • Add support for a change event (has to not be triggered when initial selected_items are removed from the drop down and added to the item box)
  • Add support for an additional role for tokens to enable rounded corners for a more tag-like appearance.
  • Change items and selected_items to accept and return actual data tables rows and internally use the display_column property to build the options in the dropdown.
    • Support formatted display like the data bindings support in anvil so the dropdown can show something like "{}: {}".format(column1, column2)"
4 Likes

Thank you for this, if the original version is not going to to be updated to easily retrieve the values, There should at least be a footnote and a link to this thread in the library/tokens post. Would have saved me hour.

2 Likes