如何解决没有框架的榆木模态 代码
我是ELM的新手,我想创建一个模态而不使用任何库,例如Bootstrap或ELM-UI。我在网上找到了这个简单的示例,该示例也在使用JSON Decode。是否有可能仅在没有任何框架/库和JSON解码的情况下进行模态工作?如何修改代码以简单地获得有效的模态?
module Main exposing (main)
import browser
import Html exposing (Html,Attribute,button,div,span,text)
import Html.Events exposing (onClick,on)
import Html.Attributes exposing (class,style)
import Json.Decode as Decode
type alias Model =
{ isVisible : Bool,count : Int }
initialModel : Model
initialModel =
{ isVisible = False,count = 0 }
type Msg
= Show
| Hide
| Increment
| Decrement
update : Msg -> Model -> Model
update msg model =
case msg of
Show ->
{ model | isVisible = True }
Hide ->
{ model | isVisible = False }
Increment ->
{ model | count = model.count + 1 }
Decrement ->
{ model | count = model.count - 1 }
view : Model -> Html Msg
view model =
div []
[ button [ onClick Show ] [ text "Show!" ],if model.isVisible then
div
([ class dialogContainerClass,on "click" (containerClickDecoder Hide)
]
++ dialogContainerStyle
)
[ div dialogContentStyle
[ span [] [ text "Click anywhere outside this dialog to close it!" ],span [] [ text "Clicking on anything inside of this dialog works as normal." ],div []
[ button [ onClick Decrement ] [ text "-" ],text (String.fromInt model.count),button [ onClick Increment ] [ text "+" ]
]
]
]
else
div [] []
]
dialogContainerClass : String
dialogContainerClass = "dialog-container-class"
containerClickDecoder : msg -> Decode.Decoder msg
containerClickDecoder closeMsg =
Decode.at [ "target","className" ] Decode.string
|> Decode.andThen
(\c ->
if String.contains dialogContainerClass c then
Decode.succeed closeMsg
else
Decode.fail "ignoring"
)
dialogContainerStyle : List (Attribute msg)
dialogContainerStyle =
[ style "position" "absolute",style "top" "0",style "bottom" "0",style "right" "0",style "left" "0",style "display" "flex",style "align-items" "center",style "justify-content" "center",style "background-color" "rgba(33,43,54,0.4)"
]
dialogContentStyle : List (Attribute msg)
dialogContentStyle =
[ style "border-style" "solid",style "border-radius" "3px",style "border-color" "white",style "background-color" "white",style "height" "120px",style "width" "440px",style "flex-direction" "column",style "justify-content" "center"
]
main : Program () Model Msg
main =
browser.sandBox
{ init = initialModel,view = view,update = update
}
解决方法
如果我正确理解了您的问题,那么您要解决的问题是在模式外部单击以将其关闭。对事件对象进行解码以获取有关DOM的信息在Elm中有点麻烦-我认为除非有必要,否则您应该尝试避免它。一种实现相同目的的方法是在模式内容中添加带有stop propagation的click事件处理程序–当容器中的click事件源于模式内部时,这可以阻止click事件在容器上触发。
我已将您的示例代码放在Ellie中,并做了一些小的更改:https://ellie-app.com/b9gDPHgtz2ca1
此解决方案使用Html.Events.stopPropagationOn,与on
类似,但调用了event.stopPropagation()
。此功能确实要求您提供解码器,所以恐怕您无法摆脱导入Json.Decode
的麻烦,但是我们正在使用最简单的解码器– Decode.succeed
–并且仅满足该功能的参数。
我在NoOp
上添加了Msg
变体,因为单击模式时无事可做。只需附加此事件处理程序,即可在我们不希望触发该事件时阻止Hide
事件。
代码
module Main exposing (main)
import Browser
import Html exposing (Attribute,Html,button,div,span,text)
import Html.Attributes exposing (class,style)
import Html.Events exposing (on,onClick)
import Json.Decode as Decode
type alias Model =
{ isVisible : Bool,count : Int }
initialModel : Model
initialModel =
{ isVisible = False,count = 0 }
type Msg
= Show
| Hide
| Increment
| Decrement
| NoOp
update : Msg -> Model -> Model
update msg model =
case msg of
Show ->
{ model | isVisible = True }
Hide ->
{ model | isVisible = False }
Increment ->
{ model | count = model.count + 1 }
Decrement ->
{ model | count = model.count - 1 }
NoOp ->
model
view : Model -> Html Msg
view model =
div []
[ button [ onClick Show ] [ text "Show!" ],if model.isVisible then
div
(onClick Hide
:: dialogContainerStyle
)
[ div
(onClickStopPropagation NoOp
:: dialogContentStyle
)
[ span [] [ text "Click anywhere outside this dialog to close it!" ],span [] [ text "Clicking on anything inside of this dialog works as normal." ],div []
[ button [ onClick Decrement ] [ text "-" ],text (String.fromInt model.count),button [ onClick Increment ] [ text "+" ]
]
]
]
else
div [] []
]
onClickStopPropagation : msg -> Html.Attribute msg
onClickStopPropagation msg =
Html.Events.stopPropagationOn "click" <| Decode.succeed ( msg,True )
dialogContainerStyle : List (Attribute msg)
dialogContainerStyle =
[ style "position" "absolute",style "top" "0",style "bottom" "0",style "right" "0",style "left" "0",style "display" "flex",style "align-items" "center",style "justify-content" "center",style "background-color" "rgba(33,43,54,0.4)"
]
dialogContentStyle : List (Attribute msg)
dialogContentStyle =
[ style "border-style" "solid",style "border-radius" "3px",style "border-color" "white",style "background-color" "white",style "height" "120px",style "width" "440px",style "flex-direction" "column",style "justify-content" "center"
]
main : Program () Model Msg
main =
Browser.sandbox
{ init = initialModel,view = view,update = update
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。