Schedule Input Focus with requestAnimationFrame to Handle Multiple DOM Mutations in Zag.js

Segun Adebayo
InstructorSegun Adebayo
Share this video with your friends

Social Share Links

Send Tweet
Published a year ago
Updated a year ago

We'll be implementing the backspace event which triggers two actions: clearFocusedValue, and focusPreviousInput.

These implementations you'll be familiar with at this point but what you'll notice when we actually try to hit backspace that the focus value will get cleared but we won't be setting focus to the previous input. This is because there are several DOM mutations happening at the same time. We'll fix this by scheduling the focus of inputs to the next animation frame with requestAnimationFrame

Instructor: [0:00] Now, let's implement the backspace event. Before we do that, if we switch over to this browser here, one of the things we set here on key down is if the event key equals escape, we're sending the backspace events. This is definitely an error there.

[0:17] We could change that over to backspace so it actually matches the DOM. We come right here into implementing the actions. Let's start with clear focus value. With clear focus value, what we can do is to set up the context.

[0:34] Here, we're basically going to grab the context value of the currently focused index and just set that to an empty string. That way we clear the focus value. The second thing here is to focus the previous input. Then we're going to come here as well.

[0:50] We've got focus next input and then we can put focus previous input in there. Then let's clean up this one right here. Then we can compute the previous index, which will most likely be a max of zero and the context value, context focus index minus one. Then we can set that to be the new focus index right there.

[1:20] This way when we hit the backspace key, it clears the value if there's a value of the current index, and then it focuses the previous input automatically. Remember in the previous lesson that we included a side effect here that tracks the focus index. Anytime that focus index gets set, we are executing the actual DOM focus, which moves the focus in the DOM.

[1:44] Let's switch over to UI and confirm that this works as expected. Reload the page and then we just type A, B, and then we hit the backspace key. We see here that this produces an unexpected effect because we wanted to actually focus the previous input and now the focus still stays at the current input instead of the previous.

[2:08] Now this usually happens when there are several DOM mutations happening at the same time. To fix this, we switch over to the execute focus event and we schedule that to move that over to the next animation frame, which basically means the next tick.

[2:23] Instead of focusing right away, we just schedule that to the next tick to do that focus after the DOM mutations.

[2:33] We put here A, B. We hit the backspace key, we see that it moves the previous input. Backspace again, it moves the previous input and then backspace again, it clears the current one. That is exactly the behavior that we want.

f1729
f1729
~ a year ago

Is a good practice to include logic that involves DOM manipulation inside the machine? I would think that the machina should only manipulate the state.

Segun Adebayo
Segun Adebayoinstructor
~ a year ago

Yes, I would consider it a good practice since the machine will need to interact with the "outside world" at some point via its actions. In this case, we're interacting with the DOM. Actions and Activities in state machines are the best way to handle those.

Markdown supported.
Become a member to join the discussionEnroll Today