Elm - 如何检测当前焦点

6

在Elm中如何获取当前焦点?我知道如何用Elm设置焦点,但是我找不到任何功能来检测当前焦点。

1个回答

9
elm-lang/dom 包允许根据 ID 设置元素的聚焦,但不允许获取当前已聚焦的元素。它提醒你可以使用document.activeElement 来实现。要做到这一点,您需要使用端口 (ports)。
这里是一个人为构造的示例。假设您有一个包含当前选定 ID 和我们即将创建的一些文本框的所有 ID 列表的Model
type alias Model =
    { selected : Maybe String
    , ids : List String
    }

我们将使用的消息可以查询焦点,并使用Dom库设置焦点:
type Msg
    = NoOp
    | FetchFocused
    | FocusedFetched (Maybe String)
    | Focus (Maybe String)

为此,我们需要两个端口:

port focusedFetched : (Maybe String -> msg) -> Sub msg

port fetchFocused : () -> Cmd msg

这些端口调用的 javascript 将报告当前的 document.activeElement:
var app = Elm.Main.fullscreen()
app.ports.fetchFocused.subscribe(function() {
  var id = document.activeElement ? document.activeElement.id : null;
  app.ports.focusedFetched.send(id);
});

视图显示当前选定的ID,并提供一个按钮列表,可将焦点设置在下面编号的文本框之一。
view : Model -> Html Msg
view model =
    div []
        [ div [] [ text ("Currently selected: " ++ toString model.selected) ]
        , div [] (List.map viewButton model.ids)
        , div [] (List.map viewInput model.ids)
        ]


viewButton : String -> Html Msg
viewButton id =
    button [ onClick (Focus (Just id)) ] [ text id ]


viewInput : String -> Html Msg
viewInput idstr =
    div [] [ input [ id idstr, placeholder idstr, onFocus FetchFocused ] [] ]

update函数将所有内容绑定在一起:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        NoOp ->
            model ! []

        FetchFocused ->
            model ! [ fetchFocused () ]

        FocusedFetched selected ->
            { model | selected = selected } ! []

        Focus (Just selected) ->
            model ! [ Task.attempt (always NoOp) (Dom.focus selected), fetchFocused () ]

        Focus Nothing ->
            { model | selected = Nothing } ! [ fetchFocused () ]

这是一个在ellie-app.com上的实际工作示例


1
我已经更新了Ellie示例,使其与Elm 0.19版本兼容:最重要的更改:(a)导入并使用Browser.Dom而不是仅使用Dom。(b)对于main函数,使用Browser.Element代替Html.program(并重新定义init值)。 (c)在update的分支中使用(model,Cmd)而不是model![cmds]形式(在Focus分支中使用(model,Cmd.batch [cmds]))。 (d)使用String.fromIntMaybe.withDefault来准备文本输出。请参见此处:https://ellie-app.com/b8bF4FXGbWca1 - awagner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接