web-dev-qa-db-fra.com

Comment mettre l'accent sur un élément dans Elm?

Comment puis-je définir le focus sur un élément Html dans Elm? J'ai essayé de définir l'attribut autofocus sur l'élément et il ne définit que le focus sur le chargement de la page.

41
Martinos

La fonction focus dans le package Elm-lang/dom est utilisée pour définir le focus avec un Task (sans utiliser de ports ou JavaScript).

En interne, il utilise requestAnimationFrame pour garantir le rendu de toutes les nouvelles mises à jour DOM avant d'essayer de trouver le nœud DOM sur lequel se concentrer.

Un exemple d'utilisation:

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

exemple complet sur Ellie

49
robertjlooby

Une solution de contournement est d'utiliser Mutation Observers . Insérez ce JavaScript dans votre page HTML principale ou dans la vue principale de votre code 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);
    }
  }
}

Créez ensuite des éléments HTML en incluant Html.Attributes.attribute "data-autofocus" "".

9
thSoft

J'ai passé pas mal de temps à l'explorer récemment. Malheureusement, je ne pense pas que ce soit possible avec le Elm-html bibliothèque. Cependant, j'ai trouvé un hack qui utilise des animations css pour déclencher un événement et l'intégrer dans des js purs.

Voici mon hack dans Elm en utilisant un nœud script et un nœud style. C'est très moche à mon avis.

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

Avec Elm/html 0,19, vous pouvez définir Html.Attrbutes autofocus sur True

input [ onInput Code, autofocus True ] []

2
Natim