Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Best way to keep focus in the input box that was just swapped #75

Closed
kzbt opened this issue May 31, 2020 · 6 comments
Closed

Best way to keep focus in the input box that was just swapped #75

kzbt opened this issue May 31, 2020 · 6 comments

Comments

@kzbt
Copy link

kzbt commented May 31, 2020

I would like the input box be focused while doing inline validation with keyup trigger.

For example:

<input 
  class="input is-danger" 
  name="name" 
  type="text" 
  value="Invalid value" 
  hx-trigger="keyup changed delay:300ms" 
  hx-target="this" 
  hx-swap="outerHTML" 
  hx-post="/validate" 
  hx-params="name">

This works and the dom gets swapped if the user has not entered anything in 300ms. But once its swapped the input focus is lost, so the user cant keep editing to correct the mistake.

I've tried using the event system, but it seems like some of the event listeners are not getting registered.

htmx.on("afterSettle.htmx", function(e) {
  console.log("This did not print");
});

However load.htmx did work.

@bencroker
Copy link
Collaborator

@kzbt I generally solve this by not replacing the input field and targetting another element instead. Is that an option for your use-case?

@1cg
Copy link
Contributor

1cg commented Jun 3, 2020

I would like to add this behaviour to htmx, but right now it doesn't preserve focus.

I think that a morphdom swap should do so, however:

https://htmx.org/extensions/morphdom-swap/

@kzbt
Copy link
Author

kzbt commented Jun 5, 2020

@bencroker I'm trying to achieve something like below, which as far as I could think of can only be accomplished by replacing the input itself (the red border on invalid input). I'm also sending a <p> which renders the error message using hx-swap-oob.
image

@chg20 I've tried it with morphdom and it doesn't seem to work with hx-target="this". I've reproduced the issue here: https://jsfiddle.net/0fkzpaew/. I used mocky.io to create a mock api but in case the link expires you can use the following as a response and use the url

<input type="text" class="error" hx-target="this" hx-swap="morphdom" hx-get="http://localhost:1999/input.html" hx-trigger="keyup changed delay:300ms"/>

I've also tried morphdom with hx-target="closest <some-elem>", it swaps but the focus is lost.

@bencroker
Copy link
Collaborator

Ok @kzbt, i see what you mean now. I was going to explore using afterSwap to reset the focus, but there is a bug in which that event is not called #79 (comment).

@1cg
Copy link
Contributor

1cg commented Jun 11, 2020

OK, first attempt at an id based fix for this:

2ac221b

@1cg 1cg closed this as completed Jun 11, 2020
strangeRabbit777 added a commit to strangeRabbit777/high-power-tool that referenced this issue Aug 23, 2022
strangeRabbit777 added a commit to strangeRabbit777/high-power-tool that referenced this issue Aug 25, 2022
@YavorK
Copy link

YavorK commented May 8, 2023

The #id solution works! You can replace the whole parent-div and the #id will make sure to put focus on the field where it was.

Here's a different solution similar to what @bencroker described -- "just replace the parts of the page you really need to replace, not the input field"
have a field <input type="text ...>
and I want to display the errors as the user types... soo I have something like:

Password: <input type="text" name="password" value=""
                         hx-trigger="keyup changed delay:1s"
                         hx-post="/register?validateField=password"
                         hx-swap="#password_error"
        ><br>
        <div id="password_error"><!-- htmx placeholder --></div>

you can see i have the imput and a "space" placeholder for the errors separately. So when I hit /register?validateField=password I can return:

<div hx-swap-oob="#password_error"
     id="password_error">
            <span style="color:red">The password must be at least 6 characters.</span><br>
    </div>

The response tells HTMX

  • hx-swap-oob="#password_error" -> find the element with this ID and swap specifically its contents.

Sooo if the user keeps typing and there is no error Backend just responds with empty div like

<div hx-swap-oob="#password_error"
     id="password_error">
    </div>

so it replaces/removes the error.

The user can keep typing since only the error <div> is replaced and the cursor/focus stays on the <input> field.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants