How to set focus on an element in Elm?

A workaround for this is to use Mutation Observers. Insert this JavaScript either in your main HTML page or in the main view of your Elm code:

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);
    }
  }
}

Then create HTML elements by including Html.Attributes.attribute "data-autofocus" "".


The focus function in the elm-lang/dom package is used to set focus with a Task (without using any ports or JavaScript).

Internally it uses requestAnimationFrame to ensure any new DOM updates are rendered before it tries to find the DOM node to focus on.

An example use:

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


With elm/html 0.19 you can set the Html.Attrbutes autofocus to True

input [ onInput Code, autofocus True ] []

Tags:

Html

Elm