How do you get all selected values from a <select multiple=multiple>?

Basically I’m trying to solve this exact same problem javascript - How to get all selected values from <select multiple=multiple>? - Stack Overflow but using Purescript + Halogen.

In the JS solution they pass the select element but here we render the select based on state, and what I want is to do the opposite, inform my Halogen component state based on what is selected on the widget. So I face a chicken egg problem.

I was thinking about adding an event handler to detect the onChange events but again looking at the documentation I don’t know how to extract specific information when the type is just the opaque Event type.

I’m not sure if there is an easier way but you can use target to get the target-Element of the event (there are other ways but I thinks this is fine here)

Having the target you can use fromEventTarget to convert this into a HTMLSelectElement and get the selected options with selectedOptions.

From this collection you can go on and extract the html-options and finally the values with similar functions as above from this module.

As I said: there is probably an easier way but this is what I could find from the documentation.


As an alternative you could write a small FFI function to use JS to make this a bit easier I guess


Also you could try and see what onValueChange produces in this case (I honestly don’t know but maybe it’s usable)

Thanks for the hint, leaving here some snippets of your solution as reference for anyone looking for same answer.

In your render portion, add an event handler for onChange, SelectModule is just the action to notify halogen component of a change here

render st = 
    .... 
    HH.select [ 
       HP.multiple true, 
       HE.onChange  $ \e -> SelectModule (extractSelect e) 
     ] [
       HH.option .....
     ]
   where
     extractSelect :: Event -> HTMLSelectElement
     extractSelect e =
       unsafePartial $ fromJust
         $ do
             et <- target e
             fromEventTarget et

then you move all the effectful computations you need to perform to your handleAction function:

handleAction = case _ of
  ...
  SelectModule m -> do
    values <-
      H.liftEffect
        $ do
            col <- selectedOptions m
            options <- toArray col
            traverse value $ catMaybes $ map fromElement options
    H.modify_ \st -> st { items = values }
  ...
1 Like