我将<div>
添加到包装器<div>
,我需要能够滚动到每次添加的最后一个。我如何在榆树中做到这一点?
<div class="messages" style="height: 7em; overflow: scroll">
<div>Anonymous: Hello</div>
<div>John: Hi</div>
</div>
直观地说,似乎我可以调用运行JavaScript代码port
的{{1}}:
element.scrollTop = element.scrollHeight
问题是AddChatMessage chatMessage ->
( { model | chatMessages = model.chatMessages ++ [ chatMessage ] } , scrollToBottomPort "div.messages" )
在scrollToBottom
更新后被称为。没什么大不了的,我把它转换成model
。但是,即使Task
现在首先更新,model
也不会更新。所以我最终滚动到底部的第二个项目!
这可能会导致我对Elm感到好奇的一个更普遍的问题,在视图因模型更改而更新视图后如何运行view
?
答案 0 :(得分:7)
您可以使用端口滚动到列表的底部 在这种情况下,您需要在执行滚动之前设置javascript以等待1个AnimationFrame。确保您的列表已呈现。
更简单的方法是使用Elm的Dom.Scroll库
并使用<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
<li><a href="#">Link 3</a></li>
<li><a href="#">Link 4</a></li>
<li><a href="#">Link 5</a></li>
<li><a href="#">Link 6</a></li>
<li><a href="#">Link 7</a></li>
<hr align="left" width="100%" color="#a2a2a2">
<hr align="left" width="100%" color="#a2a2a2">
函数。
如果您在代码中包含这样的内容:
toBottom
它应该工作。 我做了一个有效的例子here in runelm.io
答案 1 :(得分:3)
从Elm 0.19开始,使用功能Browser.Dom.getViewportOf
和Browser.Dom.setViewportOf
,每次将新元素添加到容器时,您都可以进入容器的底部。
jumpToBottom : String -> Cmd Msg
jumpToBottom id =
Dom.getViewportOf id
|> Task.andThen (\info -> Dom.setViewportOf id 0 info.scene.height)
|> Task.attempt (\_ -> NoOp)
答案 2 :(得分:1)
Dom.Scroll绝对是最佳选择,并且易于实施。
查看文档说滚动到底部:
toBottom : Id -> Task Error ()
,您可以看到它必须是一个任务,因此您可以将其包含在Task.attempt
中。例如:
Task.attempt (\_ -> NoOp) (Dom.Scroll.toBottom Id)
然后您需要一个函数将结果Error()转换为Msg,但由于滚动不太可能失败或者如果它不具有下行作用,您可以设置像(\_ -> NoOp)
这样的虚拟函数快速破解。
答案 3 :(得分:0)
因为不建议使用版本0.19 Dom
,而是可以使用Html.Attribute.property
函数设置滚动位置。
import Html exposing (Html, text)
import Html.Attributes exposing (class, property)
import Json.Encode as Encode
view : Model -> Html Msg
view model =
div [ class "flow-editor"
, property "scrollLeft" (Encode.float model.scrollLeft)
, property "scrollTop" (Encode.float model.scrollTop)
]
[ text "placeholder" ]