{{autofocus}} modifier: improving our component APIs

While building an autofocus feature for our components, we have been able to improve their APIs. Let’s see how we achieved that with the {{autofocus}} modifier.

Cyrille David
Dec 13, 2019 · 3 min read

Inviting a new admin on the company account, creating a new card, issuing a transfer. All these actions are sensitive and need to be confirmed by the user. To confirm them, we require a one-time-password to be filled from a text message. As a neobank, security is at the essence of what we do at Qonto, but we should not let it degrade the experience. This is why we want to autofocus this input.

autofocusing a component
autofocusing a component
In the following gif, see what it can look like from a user perspective.

Make the confirm action easier

Let’s automatically focus that one-time-password input. To provide the user with an indication and a starting point, so that they can easily confirm their action.

That is not the only use of such an autofocus behavior. In another one of our web apps, we prompt the user for an email address, with the goal of starting the registration process. The email input is the only relevant information on the page. In that case, we also want the input to be focused on display.

Our one-time-password input and our email input are both components. But they are not quite the same component.

This autofocus feature needs to be implemented in several components, spread across two apps. The question is: how do we share the code?

Moving towards better APIs for our components

One option would be to use a mixin, but mixins are no longer recommended in Ember ecosystem (1). Thankfully, we have a new feature in Ember for sharing code between components, similar to directives in Vue or Angular: Ember modifiers.

With a modifier, we can apply a modification to a DOM element with a function or a class. It allows us to use a component like this, notice the part:

<OTPInput
@label="Confirmation Code"
@value={{this.confirmationCode}}
{{on "update" this.updateCode}}
{{autofocus}}
/>

Modifiers are a feature planned for the next (and first!) Ember Edition (2). That feature is currently being experimented with in a third-party package: https://github.com/ember-modifier/ember-modifier.

If you want to go into the details about modifiers, you can look at this linked blog post.

Iteration #1

A simplified version of our modifier would be:

import { modifier } from 'ember-modifier';export default modifier(function autofocus(element) {
element.focus();
});

Simple.

Iteration #2

Let’s make this a bit more sophisticated, and autofocus the first non-disabled input — if it exists:

import { modifier } from 'ember-modifier';export default modifier(function autofocus(element) {
let childElement = element.querySelector('input:not([disabled])');
if (childElement) {
childElement.focus();
} else {
element.focus();
}
});

Iteration #3

Last iteration, let our modifier support taking a selector as a parameter:

<ConfirmationModal {{autofocus "#confirm-button"}}>

We’re taking advantage of the positional parameters here, that we can get in our modifier function as an array in the second parameter. Our autofocus modifier becomes like that:

import { modifier } from 'ember-modifier';export default modifier(function autofocus(element, [selector = 'input:not([disabled])']) {
let childElement = element.querySelector(selector);
if (childElement) {
childElement.focus();
} else {
element.focus();
}
});

And we can use it set the focus on an informative modal’s close button.

Conclusion: let’s use this code

The code is wrapped up in a small addon: ember-autofocus-modifier. You can use it as is. Or you could copy the code and experiment with creating you own modifier.

Thanks to this work, we can share code between multiple apps. We keep some implementations consistent while distributed.

To install the addon, run the command (or ). Then, modifier is available in your templates.

Thanks for reading!

(1) on why Mixins are not a recommended pattern anymore: https://github.com/emberjs/rfcs/issues/534

(2) you don’t know what a Ember Edition is? https://emberjs.com/editions/

Qonto ∙ Blog

Easy business banking

Cyrille David

Written by

Qonto ∙ Blog

Easy business banking

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade