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

时间:2018-03-28 18:51:37

标签: 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
        }

1 个答案:

答案 0 :(得分: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

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

相反,您可以与selection

进行比较
if choice.label == selection.label then

此外,这与该问题无关,但为什么要拨打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
    }

此处有更新的Ellie(我还清理了一些if语句):https://ellie-app.com/6KMKX9tMTa1/0