榆树视图后面更新一个消息

Mat*_*son 0 elm

我有以下代码尝试使用style-elements滚动我自己的dropMenu实现.我遇到了与style-elements包中的菜单实现相同的错误.问题是在发送另一个Msg之前,视图似乎没有在Msg上更新,这意味着视图总是落后于当前状态一步.我怎么能绕过这个?

type alias Menu =
    { label : String
    , group : Group
    , choices : List Choice
    , isOpen : Bool
    , selected : String
    }


type alias Choice =
    { label : String
    , item : Item
    , selected : Bool
    }


type Item
    = Diazepam
    | Lorazepam
    | Midazolam
    | NoneChosen


model : Menu
model =
    { label = "First line agents"
    , group = FirstLine
    , choices =
        [ { label = "Diazepam"
          , item = Diazepam
          , selected = False
          }
        , { label = "Lorazepam"
          , item = Lorazepam
          , selected = False
          }
        , { label = "Midazolam"
          , item = Midazolam
          , selected = False
          }
        ]
    , isOpen = False
    , selected = ""
    }


type Group
    = FirstLine
    | SecondLine
    | ThirdLine
    | FourthLine


menuChoice : Choice -> Element MyStyles variation Msg
menuChoice choice =
        if
            choice.selected
                == False
        then
            el Selection [ onClick (SelectChoice choice) ] (text choice.label)
        else
            el Selected [ onClick NoOp ] (text (choice.label ++ "oogityboogity"))


prepend : List a -> List a -> List a
prepend listA listB =
    List.append listB listA


menuDown : Menu -> Element MyStyles variation Msg
menuDown menu =
    column Content
        []
        (case menu.isOpen of
            True ->
                List.append
                    [ el Header [ onClick CloseMenu ] (text menu.label) ]
                    (List.map
                        (\choice ->
                            menuChoice choice
                        )
                        menu.choices
                    )

            False ->
                [ el Header [ onClick OpenMenu ] (text menu.label) ]
        )


menuUp : Menu -> Element MyStyles variation Msg
menuUp menu =
    column Content
        []
        (case menu.isOpen of
            True ->
                List.append
                    (List.map
                        (\choice ->
                            if choice.label == menu.selected then
                                menuChoice choice
                            else
                                menuChoice choice
                        )
                        menu.choices
                    )
                    [ el SubHead [] (text menu.label) ]

            False ->
                [ el SubHead [] (text menu.label) ]
        )



-- UPDATE --


update : Msg -> Menu -> Menu
update msg menu =
    case msg of
        CloseMenu ->
            { menu | isOpen = False }

        OpenMenu ->
            { menu | isOpen = True }

        SelectChoice choice ->
            markSelected menu choice

        NoOp ->
            menu


type Msg
    = CloseMenu
    | OpenMenu
    | SelectChoice Choice
    | NoOp


markSelected : Menu -> Choice -> Menu
markSelected menu selection =
    let
        newMenu =
            { menu
                | selected = selection.label
                , isOpen = False
                , choices =
                    List.map
                        (\choice ->
                            if choice.label == menu.selected then
                                { choice | selected = True }
                            else
                                { choice | selected = False }
                        )
                        menu.choices
            }
    in
        update NoOp newMenu


view : Menu -> Html.Html Msg
view model =
    Element.viewport stylesheet <| menuDown model


main =
    Html.beginnerProgram
        { model = model
        , update = update
        , view = view
        }
Run Code Online (Sandbox Code Playgroud)

Sid*_*ney 5

问题在于你的markSelected功能.这是所述功能的内容:

markSelected : Menu -> Choice -> Menu
markSelected menu selection =
    let
        newMenu =
            { menu
                | selected = selection.label
                , isOpen = False
                , choices =
                    List.map
                        (\choice ->
                            if choice.label == menu.selected then
                                { choice | selected = True }
                            else
                                { choice | selected = False }
                        )
                        menu.choices
            }
    in
        update NoOp newMenu
Run Code Online (Sandbox Code Playgroud)

您正在映射选项以更新其selected状态.要检查哪一个应该是True,你要将选择的标签与之比较menu.selected.但是menu.selected之前的菜单状态,这就是为什么模型似乎反映了一次更新的先前状态.

相反,你可以比较selection:

if choice.label == selection.label then
Run Code Online (Sandbox Code Playgroud)

此外,这与该问题无关,但你为什么要打电话update NoOp newMenu?只需返回新菜单!

markSelected : Menu -> Choice -> Menu
markSelected menu selection =
    { menu
        | selected = selection.label
        , isOpen = False
        , choices =
            List.map
                (\choice ->
                    if choice.label == selection.label then
                        { choice | selected = True }
                    else
                        { choice | selected = False }
                )
                menu.choices
    }
Run Code Online (Sandbox Code Playgroud)

这是更新的Ellie(我还清理了一些if陈述):https://ellie-app.com/6KMKX9tMTa1/0