微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

没有框架的榆木模态 代码

如何解决没有框架的榆木模态 代码

我是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 举报,一经查实,本站将立刻删除。