如何在 Elm 中设置焦点?

Posted

技术标签:

【中文标题】如何在 Elm 中设置焦点?【英文标题】:How to set focus on an element in Elm? 【发布时间】:2015-11-01 07:05:33 【问题描述】:

如何将焦点设置在 Elm 中的 html 元素上?我尝试在元素上设置 autofocus 属性,它只将焦点设置在页面加载上。

【问题讨论】:

【参考方案1】:

elm-lang/dom 包中的focus 函数用于通过Task 设置焦点(不使用任何ports 或javascript)。

在内部,它使用requestAnimationFrame 确保在尝试查找要关注的 DOM 节点之前呈现任何新的 DOM 更新。

使用示例:

type Msg
    = FocusOn String
    | FocusResult (Result Dom.Error ())

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        FocusOn id ->
            ( model, Dom.focus id |> Task.attempt FocusResult )

        FocusResult result ->
            -- handle success or failure here
            case result of
                Err (Dom.NotFound id) ->
                    -- unable to find dom 'id'
                Ok () ->
                    -- successfully focus the dom

Full example on Ellie

【讨论】:

请注意,这确实有效,但我发现如果动态添加元素,它可能会在意外时间静默失败。 你有失败的例子吗? 不幸的是,我现在没有可重现的示例。如果我找到另一个,我会回帖。总的来说,这绝对是正确的做法,所以我的评论应该被忽略,直到我找到一个具体的案例:) "如果元素不可见,设置焦点可能会静默失败。" package.elm-lang.org/packages/elm-lang/dom/latest/Dom#focus 如果使用 Elm 0.19,这个包现在是 elm/browser 的一部分。【参考方案2】:

解决方法是使用Mutation Observers。将此 JavaScript 插入您的主 HTML 页面或 Elm 代码的主视图中:

var observer = new MutationObserver(function(mutations) 
  mutations.forEach(function(mutation) 
    handleAutofocus(mutation.addedNodes);
  );
);
var target = document.querySelector('body > div');
var config =  childList: true, subtree: true ;
observer.observe(target, config);

function handleAutofocus(nodeList) 
  for (var i = 0; i < nodeList.length; i++) 
    var node = nodeList[i];
    if (node instanceof Element && node.hasAttribute('data-autofocus')) 
      node.focus();
      break;
     else 
      handleAutofocus(node.childNodes);
    
  

然后通过包含 Html.Attributes.attribute "data-autofocus" "" 来创建 HTML 元素。

【讨论】:

【参考方案3】:

我最近花了很多时间探索这个。不幸的是,我认为现有的elm-html 库是不可能的。然而,我想出了一个利用 css 动画触发事件并将其嵌入到纯 js 中的 hack。

这是我在 Elm 中使用 script 节点和 style 节点的 hack。在我看来这是非常丑陋的。

import Html exposing (div, button, text, input, node)
import Html.Events exposing (onClick)
import Html.Attributes exposing (type', class)
import StartApp.Simple

main =
  StartApp.Simple.start  model = model, view = view, update = update 

model = []

view address model =
  -- View now starts with a <style> and <script> (hacky)
  (node "style" [] [ Html.text style ]) ::
  (node "script" [] [Html.text script ]) ::
  (button [ onClick address AddInput ] [ text "Add Input" ]) ::
  model |>
  div []    

type Action = AddInput 

update action model =
  case action of
    AddInput -> (Html.p [] [input [type' "text", class "focus"] []]) :: model

-- Use pure string css (hacky)

style = """
.focus 
  animation-name: set-focus;
  animation-duration: 0.001s;
  -webkit-animation-name: set-focus;
  -webkit-animation-duration: 0.001s;

@-webkit-keyframes set-focus 
    0%   color: #fff

@keyframes set-focus 
    0%   color: #fff

"""

-- Cheating by embedding pure javascript... (hacky)

script = """
var insertListener = function(event)
 if (event.animationName == "set-focus") 
   event.target.focus();
                

document.addEventListener("animationstart", insertListener, false); // standard + firefox
document.addEventListener("MSAnimationStart", insertListener, false); // IE
document.addEventListener("webkitAnimationStart", insertListener, false); // Chrome + Safari
"""

【讨论】:

【参考方案4】:

使用 elm/html 0.19,您可以将 Html.Attrbutes autofocus 设置为 True

input [ onInput Code, autofocus True ] []

【讨论】:

这似乎不能可靠地工作,我打开了一个问题here。 是的,Dom.focus id |&gt; Task.attempt FocusResult 更可靠 这在文件中也需要import Browser.Dom,例如这里package.elm-lang.org/packages/elm/core/latest/Task#attempt【参考方案5】:

在 Elm 0.19 中,使用 Browser.Dom.focus:

import Browser.Dom as Dom
import Task

type Msg
    = NoOp

focusSearchBox : Cmd Msg
focusSearchBox =
    Task.attempt (\_ -> NoOp) (Dom.focus "search-box")

如果对焦失败,您可以选择忽略,或者通过触发更新消息来执行某些操作。

【讨论】:

以上是关于如何在 Elm 中设置焦点?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 mat-select 中设置自动对焦?

在 ios7 xcode 中设置相机焦点。 opencv

如何在 UIView 中设置滚动视图以向上滑动被键盘隐藏的文本字段?

在 QWebView 中设置文本输入焦点

在相机android中设置矩形焦点

Extjs - 在面板中设置焦点字段