Instant search issues

I’m trying to create an instant search and faced the following issues:

  • When submitting as GET, my input box loses focus and have to click on the input again with every press of the key, any built-in method for the input box to retain focus?
  • When submitting as POST, the URL does not reflected the search term, any built-in method to add it in?
import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
    search() {
        clearTimeout(this.timeout);
        this.timeout = setTimeout(() => {
            this.element.requestSubmit();
            this.element.firstElementChild.focus();
        }, 200);
    }
}

My preference would be to use GET since it is normally what’s used in a legacy (non-turbo) search.

Currently, I’m using a Stimulus controller to perform the auto submit, I could modify it to focus on the input box, but the code above doesn’t focus on the input text.

I also don’t want the controller to only work on this single form, I would like it to also work on other instant submit forms.

Thank you.

1 Like

Are you saying when you use GET you loose focus, but when you use POST you don’t loose focus?

Are you saying when you use GET you loose focus, but when you use POST you don’t loose focus?

Yes, exactly. btw I found your post about this on another conversation. Working through it to find a solution Writing better StimulusJS controllers | Boring Rails: Skip the bullshit and ship fast

Can you share some of the HTML you are using and how you are performing the instant search with each keystroke?

// form that is not in a turbo frame
<form action="/prototype" method="POST"
    data-turbo-frame="listings see_more_listings"
    data-turbo-action="advance" data-controller="instant-submit">
    <input placeholder="" autocomplete="off" type="search" value=""
        data-action="input->instant-submit#search" name="search">
</form>

// instant_submit_controller.js
import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
    search() {
        clearTimeout(this.timeout);
        this.timeout = setTimeout(() => {
            this.element.requestSubmit();
            this.element.firstElementChild.focus();
        }, 200);
    }
}

I did not know multiple edits can cause a post to become hidden, just wanted to share this code since we are currently both active, might delete this post after the original one becomes visible again

The code includes two turbo-frames listings see_more_listings, but I believe you can only target one at a time.

1 Like

Do you mean that is the cause of the loss of focus?

Correct. When turbo evaluates the tag, it looks at the value of data-turbo-frame. If it’s an invalid value, then it will send the request as a standard turbo-drive request instead of a turbo-frame request. If you look at your browsers dev tools network you will likely see a fetch request, but if you look at the details of the request you won’t see a Turbo-Frame request header. If you remove data-turbo-frame you will see the same behavior you are seeing. The turbo-drive request will replace the entire body of the page, which would cause you to loose focus.

Change the data-turbo-frame to a single turbo-frame id and you will not loose focus.

If you need to update more than 2 areas of the page, consider nesting a turbo-stream inside a turbo-frame.

1 Like

Thanks! I now have only 1 frame and no more losing focus! How does the HTML response of a nested turbo-stream look like?

1 Like

Ok thanks! Let me try!