我有以下代码尝试使用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
}
答案 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