html - poner - ¿Cómo establecer el foco en un elemento en Elm?
poner el foco en un input jquery (3)
¿Cómo puedo establecer el foco en un elemento Html en Elm? Traté de establecer el atributo de enfoque automático en el elemento y solo establece el foco en la carga de la página.
La función de focus
en el paquete elm-lang/dom se usa para establecer el foco con una Task
(sin usar ningún port
o JavaScript).
Internamente, utiliza requestAnimationFrame
para garantizar que se requestAnimationFrame
las nuevas actualizaciones DOM antes de que intente encontrar el nodo DOM en el que enfocarse.
Un ejemplo de uso:
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
Pasé bastante tiempo explorando esto recientemente. Lamentablemente, no creo que sea posible con la biblioteca elm-html
existente. Sin embargo, se me ocurrió un truco que utiliza animaciones css para desencadenar un evento e insertarlo en js puros.
Aquí está mi hack en Elm usando un nodo de script
y un nodo de style
. Es muy feo en mi opinión.
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
"""
Una solución para esto es usar Mutation Observers . Inserte este JavaScript en su página HTML principal o en la vista principal de su código de 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);
}
}
}
Luego, cree elementos HTML incluyendo Html.Attributes.attribute "data-autofocus" ""
.