Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Elm, how can I detect if focus will be lost from a group of elements?

Tags:

json

dom

events

elm

Suppose I have a form with a number of components. I'd like to detect a los of focus from the group. So, focus from 1 input to another on the same form should be ignored. How can I achieve this?

like image 879
Mark Bolusmjak Avatar asked Jan 01 '23 20:01

Mark Bolusmjak


1 Answers

First, we want to be able to tag each focusable element within the group with some attribute, so when we switch elements we'll know if we're in the same group or not. This can be achieved with data attributes.

groupIdAttribute groupId =
    Html.Attributes.attribute "data-group-id" groupId

Next, we need to decode the event payload on an onBlur event to see if the target is different from the relatedTarget (that which will get the focus). And report the change. (note that here we refer to data-group-id via the path "dataset", "groupId")

decodeGroupIdChanged msg =
    Json.Decode.oneOf
        [ Json.Decode.map2
            (\a b ->
                if a /= b then
                    Just a

                else
                    Nothing
            )
            (Json.Decode.at [ "target", "dataset", "groupId" ] Json.Decode.string)
            (Json.Decode.at [ "relatedTarget", "dataset", "groupId" ] Json.Decode.string)
        , Json.Decode.at [ "target", "dataset", "groupId" ] Json.Decode.string
            |> Json.Decode.andThen (\a -> Json.Decode.succeed (Just a))
        ]
        |> Json.Decode.andThen
            (\maybeChanged ->
                case maybeChanged of
                    Just a ->
                        Json.Decode.succeed (msg a)

                    Nothing ->
                        Json.Decode.fail "no change"
            ) 

Now we can create an onGroupLoss listener:

onGroupFocusLoss msg =
    Html.Events.on "blur" (decodeGroupIdChanged msg)

And rig it up like so:

input [onGroupFocusLoss GroupFocusLoss, groupIdAttribute "a"]

Here is an example (note that it is built with elm-ui so there's a little extra code.)

https://ellie-app.com/3nkBCXJqjQTa1

like image 168
Mark Bolusmjak Avatar answered Jan 05 '23 14:01

Mark Bolusmjak