在 Elm 中更新 contenteditable div 时光标位置丢失

5nd*_*ndG 6 html contenteditable elm

在 contenteditable div 中输入内容时,如何使光标保持在正确的位置?

我正在使用 Elm 创建一个文本框,并且我需要在每次输入时处理框中的文本。使用 contenteditable div 而不是 textarea 的原因是我需要能够识别某些单词并在您键入时将它们变成可点击的链接。

问题是,当文本更新时,光标会返回到文本的开头,因此所有内容都是从后到前输入的。

这是一个演示该问题的最小示例:

module Main exposing (..)

import Html
import Html.Events as Hev
import Html.Attributes as Hat
import Json.Decode as Json

main : Program Never Model Msg
main =
    Html.beginnerProgram
        { model = ""
        , update = update
        , view = view
        }

type Msg = NewText String

type alias Model = String

view : Model -> Html.Html Msg
view model =
    Html.div
        [ Hat.contenteditable True
        , Hev.on "input" (Json.map NewText targetTextContent)
        , Hat.style
            [ ("border", "1px solid darkgray") ]
        ]
        [ Html.text model
        ]

targetTextContent : Json.Decoder String
targetTextContent =
    Json.at ["target", "innerText"] Json.string

update : Msg -> Model -> Model
update msg model =
    case msg of
        NewText text -> text
Run Code Online (Sandbox Code Playgroud)

Tai*_*ils 0

这似乎与这里的问题非常相似:Elm - textarea Selection range消失

存在的问题是,当 Elm 比较并重新渲染视图并保留 HTML 时,浏览器不会重新渲染更改后的选择属性。我使用一种 hack 解决了这个问题,该 hack 在每次迭代时都会回流内容,从而强制元素实际重新渲染,并正确应用选择属性。

在模型中放置一个计数器,并在每次渲染视图时增加它。然后交替在文本框元素前面插入一个空 div。( if i % 2 == 0 ...)