How to: focus an element when entering in route

Hi !

I try to achieve a simple thing : Focus an input when user entering in the route.

First I was looking for something similar to didInsertElement for controller, but there is nothing similar.

Then I tried to use the didTransation of the route to call a method on a controller to focus the input, but the didTransation is called before the dom is ready. I can used the didTransation with a call to next (from @ember/runloop) but it looks weird.

Finally I decide to implement it with modifier on the input itself (an auto-focus modifier) & it works well.

But I’m wonder if there is another “ember way” to allow controller to interact with dom element (aka. in the route template) for this kind of purpose ?

Thx !

1 Like

I think using an {{auto-focus}} modifier is the ideal way to implement this (and is also what we do in our app :wink: ). So I’d say you arrived at the ideal solution here on your own!

1 Like

Welcome @Romgere!

But I’m wonder if there is another “ember way” to allow controller to interact with dom element (aka. in the route template) for this kind of purpose ?

As @francesconovy confirmed, modifiers give you a better way to manage this kind of behavior in your application. I wanted to jot down a few notes as to why.

I’ve worked in an Ember application that started with Ember 1.12. As with any single page application, <input autofocus="true"> doesn’t do what you might think. In Ember’s routing behavior, it is also quite tricky to get predictable timing for DOM operations from controller hooks or actions. The runloop is an internal implementation detail of Ember and is theoretically not part of the Octane programming model. So in most cases you shouldn’t need to use those functions.

Early on I wrote 2 or more different versions of that approach. Something like:

// in a route
	setupController(controller, model) {
		super.setupController(...arguments);
		try {
		  document.querySelector('#myFormField').focus();
		} catch (err) {
		}
	}

Over time, this becomes a liability in your application’s design. The controller now needs to know about the specific user interface details. Phrased differently, it does not abide by “the separation of concerns” principle. For example, if someone else working in the application changed the DOM id of the component this route code would break.

In contrast, using the modifier keeps the responsibility for autofocusing within the component. The component can worry about autofocusing and other implementation details of templates and the DOM. The controller and the route, then, don’t need to worry about those details. They stick to loading the data your route template and components need.

I’m still learning how to use modifiers too, so I may have missed some details. But at the end of the day I can write something wonderfully simple:

<input
	placeholder="Give me your data. Please?"
	required="true"
	type="text"
	{{autofocus}}
 >

The last point: modifiers enable “declarative programming”. Declarative programming opens up doors for authoring well-designed applications. Chris Garret’s (@pzuraq) series on reactivity tours this concept in the context of Ember. Edward Faulkner (@ef4) also gave a talk on the differences between declarative and imperative programming.

3 Likes

An implementation of an autofocus identifier could be found here: https://github.com/qonto/ember-autofocus-modifier

1 Like