Can you dynamically specify a list of choice items?
smithandrewl opened this issue · comments
In the following example from the documentation, choiceItem objects are specified as static constructor parameters to the choiceItems class.
My question is, is it possible to pass a dynamically created list of choiceItem objects (literally a sequence or list of choiceItem) to a choiceItems constructor? How can I build a dynamic list of choiceItems?
I used map to create a sequence of choiceItem instances, but I can't pass it to the choiceItems constructor as it gets a compiler error.
Example Of Static Item Choices:
// Conditional item of overflow menu:
sectionBlock(
text = md"Test 2",
accessory = overflow(
action_id = SlackActionId("-"),
options = choiceItems(
choiceItem( text = pt"test-menu-item 1", value = "1" ),
choiceItem( text = pt"test-menu-item 2", value = "2" ),
optionally( someUserParam > 0 ) ( choiceItem( text = pt"conditional-menu-item 3", value = "3" ) )
)
)
)
Hey,
The reason you (probably) receive a compiler error, that you trying to use choiceItems
with Seq[] of choiceItem directly. However choiceItems
expects a lazy-computed list of items (to be able to use optional/conditional code as in your example).
So it is something like this:
choiceItems(
Seq(
(
() => choiceItem( text = pt"test-menu-item 1", value = "1" )
),
(
() => choiceItem( text = pt"test-menu-item 2", value = "2" )
)
):_*
)
Yet, it is cumbersome and I don't recommend it in case you just need a list of choice items, and you can use NonEmptyList
directly instead of choiceItems
:
sectionBlock(
text = md"Test 2",
accessory = overflow(
action_id = SlackActionId("-"),
options = NonEmptyList.fromListUnsafe(
List(
choiceItem( text = pt"test-menu-item 1", value = "1" )
)
)
)
)
fromListUnsafe
- now this is important to understand, you can't have an empty list of choices, and this will throw an exception in that case. Look at https://typelevel.org/cats/datatypes/nel.html for details.
To clarify, if you have at least one static choice, it is better to use NonEmptyList
with it and avoid fromListUnsafe
construction if possible.
And the most safer option would be this:
sectionBlock(
text = md"Test 2",
accessory =
// Our dynamic list data
List(
choiceItem( text = pt"test-menu-item 1", value = "1" ),
choiceItem( text = pt"test-menu-item 1", value = "1" )
) match {
case head :: tail =>
// Yay, we have at least on choice
Some(
overflow(
action_id = SlackActionId("-"),
options = NonEmptyList(head, tail)
)
)
case _ => {
// Fallback, we have no data to show as options, so we don't use overflow at all
None
}
}
)
Hope this helps. Let me know if something isn't clear.
To avoid confusion with this behaviour, I made some changes in 3.0.2 that provide an ability to use choiceItems
(and similar construction) with just any Iterable
. I'll release it soon.
Thanks so much!