RamiroPastor
RamiroPastor

Reputation: 1175

Elm - how to close modal window on outside click

This is the code:

modalWindow :
  Lang -> String ->
  Action -> Action ->
  List (Html Action) -> Html Action
modalWindow lang heading accept close inputs =
  let
    cancel = case lang of
      Es -> "Cancelar"
      En -> "Cancel"
    buttons =
      H.div [A.class "flex-center-div"]
        [ H.input
            [ A.class "textarea-editor-modal-button"
            , A.type_ "button"
            , A.value "OK"
            , E.onClick accept
            ] []
        , H.input
            [ A.class "textarea-editor-modal-button"
            , A.type_ "button"
            , A.value cancel
            , E.onClick close
            ] []
        ]
  in
    H.div [A.class "textarea-editor-modal-window", E.onClick close]
      [ H.div [A.class "textarea-editor-modal-content"] <|
          [ H.div [A.class "textarea-editor-modal-title"] [H.text heading] ]
          ++ inputs ++ [buttons]
      ]

The problem is in the line just after the in because it will close the modal even if i click on the inside of it.

According to https://www.w3schools.com/howto/howto_css_modals.asp i should be using event.target to distinguish between clicks inside or outside the inner part.

Upvotes: 2

Views: 650

Answers (2)

RamiroPastor
RamiroPastor

Reputation: 1175

modalWindow :
  Lang -> String ->
  Action -> Action ->
  List (Html Action) -> Html Action
modalWindow lang heading accept close inputs =
  let
    cancel = case lang of
      Es -> "Cancelar"
      En -> "Cancel"
    buttons =
      H.div [A.class "flex-center-div"]
        [ H.input
            [ A.class "textarea-editor-modal-button"
            , A.type_ "button"
            , A.value "OK"
            , E.onClick accept
            ] []
        , H.input
            [ A.class "textarea-editor-modal-button"
            , A.type_ "button"
            , A.value cancel
            , E.onClick close
            ] []
        ]
  in
    H.div
      [ A.class "textarea-editor-modal-window"
      , E.onClick close
      ]
      [ H.div
          [ A.class "textarea-editor-modal-content"
          , E.onWithOptions
              "click"
              {stopPropagation = True, preventDefault = False}
              (succeed NoOp)
          ]
          <|
          [ H.div [A.class "textarea-editor-modal-title"] [H.text heading]
          ] ++ inputs ++ [buttons]
      ]

I followed (@Simon H) comment and it works! (only works with "mousedown" if i use E.onMouseDown on the wrapper too, but also works if i use click on both places)

Upvotes: 1

Simon H
Simon H

Reputation: 21005

you suggestion could work, or you could add a onMouseDown eventhandler to the first div inside with a decoder that always succeeds and with preventDefault = True. the only issue is that you need to add a NoOp message

mouseDownPreventDefault : msg -> Attribute msg
mouseDownPreventDefault noop =
    onWithOptions "mousedown"
        { stopPropagation = False
        , preventDefault = True
        }
        (Json.Decode.succeed noop)

Upvotes: 4

Related Questions