web-dev-qa-db-ja.com

Elmの要素にフォーカスを設定するにはどうすればよいですか?

ElmのHtml要素にフォーカスを設定するにはどうすればよいですか?要素にautofocus属性を設定しようとしましたが、ページの読み込みにのみフォーカスが設定されます。

41
Martinos

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

Ellieの完全な例

49
robertjlooby

これの回避策は 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要素を作成します。

9
thSoft

私は最近これを調査するのにかなりの時間を費やしました。残念ながら、既存のElm-htmlライブラリを使用することはできません。しかし、CSSアニメーションを使用してイベントをトリガーし、それを純粋なjsに埋め込むハックを思いつきました。

以下は、scriptノードとstyleノードを使用したElmでのハックです。それは私の見解では非常に醜いです。

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
Joe

Elm/html 0.19で Html.Attrbutes autofocus をTrueに設定できます

input [ onInput Code, autofocus True ] []

2
Natim