# Octane, trying to set the focus to an OK button on a 'modal' dialog

**URL:** <https://discuss.emberjs.com/t/octane-trying-to-set-the-focus-to-an-ok-button-on-a-modal-dialog/20507>\
**Category:** Uncategorized\
**Created:** [May 15, 2024, 3:11pm UTC](https://discuss.emberjs.com/t/octane-trying-to-set-the-focus-to-an-ok-button-on-a-modal-dialog/20507 "2024-05-15T15:11:29Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![b-rlw](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/b-rlw/32/18306_2.png) [@b-rlw](https://discuss.emberjs.com/u/b-rlw)\
**Post date:** [May 15, 2024, 3:11pm UTC](https://discuss.emberjs.com/t/octane-trying-to-set-the-focus-to-an-ok-button-on-a-modal-dialog/20507/1 "2024-05-15T15:11:29Z")

</div>

When my component receives an authentication error, I want to display an error to the user.

This part works. I ALSO want to set the focus to the OK button. This part does NOT work.

Looking for answers show a lot of outdated ember versions (I’m using 5.4) that I don’t know how to apply. I assume there’s a quick and easy answer, but I don’t know what it is.

> ```
> showAuthenticationError() {
> this.hasAuthenticationError = true
> let okbutton = this.element.querySelector('#login-page-error-OK-button')
> okbutton.foucus()
> }
> 
> ```

> ```
> {{#if this.hasAuthenticationError}}
> <Bui::FormAlert
> @type="error" @isModal={{true}} @subject="Authentication Failed!"
> @on-click-away={{this.clearAuthenticationError}}>
> <p class="text-sm">The user name you provided is not valid, or the associated account is inactive, or the entered password is incorrect.</p>
> <p class="text-sm">Please try again.</p>
> <div class="flex justify-center mt-2">
> <button id="login-page-error-OK-button" type="button" {{on "click" this.clearAuthenticationError}}
> class="bg-gray-100 w-1/2 py-2 px-2 shadow outline-none focus:bg-gray-300 hover:bg-gray-300">OK</button>
> </div>
> </Bui::FormAlert>
> {{/if}}
> 
> ```

 ![image](https://us1.discourse-cdn.com/flex019/uploads/emberjs_public/original/3X/a/c/aceff9d23dc81137fcf2a49aeb27df7e1b598c24.png)

---

<div class="post-metadata">

**Author:** ![dknutsen](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/dknutsen/32/16471_2.png) [@dknutsen](https://discuss.emberjs.com/u/dknutsen)\
**Post date:** [May 15, 2024, 3:27pm UTC](https://discuss.emberjs.com/t/octane-trying-to-set-the-focus-to-an-ok-button-on-a-modal-dialog/20507/2 "2024-05-15T15:27:31Z")

</div>

I think there are a couple things you could do here. As the error states `this.element` no longer exists, so you can:

1. just query the `document` instead, if you’re sure that is specific enough

```auto
    let okbutton = document.querySelector('#login-page-error-OK-button')

```

1. assign an element id manually to your component, and scope your query based on the component first then the button
2. write a simple modifier which could focus it’s element when (for example) a condition is met

```auto
        <button id="login-page-error-OK-button" type="button" {{on "click" this.clearAuthenticationError}} {{focus-when this.hasAuthenticationError}} ...>

```

---

<div class="post-metadata">

**Author:** ![b-rlw](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/b-rlw/32/18306_2.png) [@b-rlw](https://discuss.emberjs.com/u/b-rlw)\
**Post date:** [May 15, 2024, 3:47pm UTC](https://discuss.emberjs.com/t/octane-trying-to-set-the-focus-to-an-ok-button-on-a-modal-dialog/20507/3 "2024-05-15T15:47:51Z")

</div>

The OK button is in the contents of a component that is conditionally displayed. So, I think the problem is that the dialog hasn’t rendered yet.

In showAuthenticationError(), the flag, hasAuthenticationError, is set to true, and then immediately, the query for the button that will exist happens before it exists.

How would I test this to see if that’s true? Is there a post update message/function to use?

---

<div class="post-metadata">

**Author:** ![dknutsen](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/dknutsen/32/16471_2.png) [@dknutsen](https://discuss.emberjs.com/u/dknutsen)\
**Post date:** [May 15, 2024, 4:05pm UTC](https://discuss.emberjs.com/t/octane-trying-to-set-the-focus-to-an-ok-button-on-a-modal-dialog/20507/4 "2024-05-15T16:05:11Z")

</div>

Actually reading the code again can you just skip all the js and add the `autofocus` attribute to the button so it focuses when rendered?

---

<div class="post-metadata">

**Author:** ![b-rlw](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/b-rlw/32/18306_2.png) [@b-rlw](https://discuss.emberjs.com/u/b-rlw)\
**Post date:** [May 15, 2024, 4:54pm UTC](https://discuss.emberjs.com/t/octane-trying-to-set-the-focus-to-an-ok-button-on-a-modal-dialog/20507/5 "2024-05-15T16:54:54Z")

</div>

Sadly, no, that doesn’t work.

\<button id=“login-page-error-OK-button” **autofocus** type=“button” {{on “click” this.clearAuthenticationError}}

However, I found this gem on your site.

**{{autofocus}}**

[Template Lifecycle, DOM, and Modifiers - Components - Ember Guides (emberjs.com)](https://guides.emberjs.com/release/components/template-lifecycle-dom-and-modifiers/#toc_abstracting-the-logic-into-a-custom-modifier)

---

<div class="post-metadata">

**Author:** ![dknutsen](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/dknutsen/32/16471_2.png) [@dknutsen](https://discuss.emberjs.com/u/dknutsen)\
**Post date:** [May 15, 2024, 9:24pm UTC](https://discuss.emberjs.com/t/octane-trying-to-set-the-focus-to-an-ok-button-on-a-modal-dialog/20507/6 "2024-05-15T21:24:05Z")

</div>

Ah nice that would have been my next suggestion

---

<div class="post-metadata">

**Author:** ![b-rlw](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/b-rlw/32/18306_2.png) [@b-rlw](https://discuss.emberjs.com/u/b-rlw)\
**Post date:** [May 15, 2024, 9:53pm UTC](https://discuss.emberjs.com/t/octane-trying-to-set-the-focus-to-an-ok-button-on-a-modal-dialog/20507/7 "2024-05-15T21:53:51Z")

</div>

Is this an actual improvement or is there an easier way? The autofocus modifier only works for base level tags and not components. I have a fancy text box component with a label, error message and fancy border elements, etc. I’m very proud of it! 🙂

To get {{autofocus}} to work on components I came up with putting an attribute, focus-target, on the element in the component that should have the focus. Then {{autofocus}} will find that and put the focus there.

But, is there a better way?

````auto
import { modifier } from 'ember-modifier';

export default modifier(function autofocus(element, ) {

    function singleElement(element) {
        switch(element?.tagName) {
            case 'INPUT':
            case 'TEXTAREA':
            case 'BUTTON':
                element.focus()
                return true 
        }
        return false
    }
    
    if( !singleElement(element) ) {
        singleElement(element.querySelector( "[focus-target]" ))
    }
})```
````

---

<div class="post-metadata">

**Author:** ![dknutsen](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/dknutsen/32/16471_2.png) [@dknutsen](https://discuss.emberjs.com/u/dknutsen)\
**Post date:** [May 15, 2024, 11:35pm UTC](https://discuss.emberjs.com/t/octane-trying-to-set-the-focus-to-an-ok-button-on-a-modal-dialog/20507/8 "2024-05-15T23:35:13Z")

</div>

There are a couple things you can do, although I’m not 100% it’s what fits your needs the best. Off the top of my head…

One option is that you can add modifiers to a component that has splattributes:

```auto
// my-fancy-input.hbs
<div> <!-- some container -->
  <label>{{@label}}</label>
  <input
    foo=bar
    ...attributes <!-- this is the "splattributes", where attributes and modifiers are forwarded -->
  >
  {{#if @error}}
    error here, etc
  {{/if}}
</div>

// somewhere else
<MyFancyInput {{autofocus}} />
              ^ this will get forwarded to the splattributes, so the <input> tag

```

you could also add the modifier _inside_ your component, and (assuming you dont’ want it to always autofocus) add an extra arg, something like:

```auto
// my-fancy-input.hbs
<div> <!-- some container -->
  <label ...>{{@label}}</label>
  <input
    foo=bar
    {{autofocus enabled=@autofocus}} <!-- this is where attributes and modifiers are forwarded -->
  >
  {{#if @error}}
    error here, etc
  {{/if}}
</div>

// somewhere else
<MyFancyInput @autofocus={{true}} />

```

yet another option would be to yield the actual input out contextually and then apply the autofocus modifier to it, although that doesn’t seem like what you want.

finally you could whip up some javascript and put it in the component or make the modifier more sophisticated (like you’ve already done)

---

<div class="post-metadata">

**Author:** ![b-rlw](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/b-rlw/32/18306_2.png) [@b-rlw](https://discuss.emberjs.com/u/b-rlw)\
**Post date:** [May 16, 2024, 2:09pm UTC](https://discuss.emberjs.com/t/octane-trying-to-set-the-focus-to-an-ok-button-on-a-modal-dialog/20507/9 "2024-05-16T14:09:26Z")

</div>

Thank you, I will try these out!
