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

Infinite loop when calling setFocus on new calcite-input #5882

Closed
nwhittaker opened this issue Dec 2, 2022 · 14 comments
Closed

Infinite loop when calling setFocus on new calcite-input #5882

nwhittaker opened this issue Dec 2, 2022 · 14 comments
Assignees
Labels
4 - verified Issues that have been released and confirmed resolved. ArcGIS Field Apps Issues logged by ArcGIS Field Apps team members. bug Bug reports for broken functionality. Issues should include a reproduction of the bug. p - high Issue should be addressed in the current milestone, impacts component or core functionality regression Issues that are caused by changes in a release, but were working before that.

Comments

@nwhittaker
Copy link
Contributor

Actual Behavior

Programmatically inserting a <calcite-input> into a <calcite-modal> and calling setFocus() on the input results in an infinite loop that locks up the window.

Expected Behavior

Programmatically inserting a <calcite-input> into a <calcite-modal> and calling setFocus() on it shifts focus to the input.

Reproduction Sample

https://codepen.io/nwhittaker-esri/pen/VwdEody

Reproduction Steps

  1. Visit the sample.
  2. Wait for the modal to open and click the Add input button.
  3. Notice the preview area locks up after a few seconds, and the browser presents some sort of Page Unresponsive dialog after awhile.

Reproduction Version

next.653

Relevant Info

The regression appears to have been introduced over a couple releases:

  1. next.632: refactor(modal): Update modal to use focus-trap module. #5676
    • Browser does not lock up, but new input elements do not gain immediate focus.
  2. next.636: fix: setFocus methods should wait for the component to be loaded #5749
    • Browser locks up when setting focus on the new input element.

The likely root of the problem is the new focus trap library isn't aware of the new input element yet, so it thinks an element outside of the modal is being focused. The loop that emerges is:

  1. setFocus() called on the new <calcite-input>.
  2. focus() called on the shadow <input>.
  3. The focus traps's focusin handler reverts focus to the previously focused element.
  4. The <calcite-input> element's focus handler runs and calls setFocus() on itself which leads back to step 1.

Regression?

next.631

Impact

The Field Maps web app uses a modal for editing coded value domains. When a user wants to add a new coded value, a new row of inputs is inserted and focus should shift to the row's first input. This is blocking us from upgrading Calcite beyond next.631.

Esri team

ArcGIS Field Apps

@nwhittaker nwhittaker added bug Bug reports for broken functionality. Issues should include a reproduction of the bug. 0 - new New issues that need assignment. needs triage Planning workflow - pending design/dev review. regression Issues that are caused by changes in a release, but were working before that. labels Dec 2, 2022
@github-actions github-actions bot added the ArcGIS Field Apps Issues logged by ArcGIS Field Apps team members. label Dec 2, 2022
@benelan
Copy link
Member

benelan commented Dec 2, 2022

Yeah, now this one isn't a doc cleanup issue 😬

Triaging to the current sprint, cc @driskull @geospatialem

@benelan benelan added the p - high Issue should be addressed in the current milestone, impacts component or core functionality label Dec 2, 2022
@benelan benelan added this to the Sprint 2022/12/04 - 2022/12/15 milestone Dec 2, 2022
@driskull
Copy link
Member

driskull commented Dec 2, 2022

I think this might be because when the modal is opened it is trapping focus. We might need to provide an option to disable focus trap for modal here.

@driskull driskull self-assigned this Dec 2, 2022
@driskull
Copy link
Member

driskull commented Dec 6, 2022

@eriklharper can you take this one? It seems like an issue with calcite-input. It works fine if a native input is used.

I narrowed it down to a infinite loop in setFocus/input

When setFocus() is called it focuses on the child element.

https://github.com/Esri/calcite-components/blob/0a658c3e4fca54a0b3275b85943dd519a8af6572/src/components/input/input.tsx#L535

The problem is when the input is focused, it calls setFocus() again if the target doesn't match the slottedActionEl. So then it gets into a never ending loop.

https://github.com/Esri/calcite-components/blob/0a658c3e4fca54a0b3275b85943dd519a8af6572/src/components/input/input.tsx#L623-L629

@driskull
Copy link
Member

driskull commented Dec 6, 2022

It actually has nothing to do with the modal. If you append the input's to the body it freezes as well.

I'm guessing input-number and input-text are also affected

@driskull driskull assigned eriklharper and unassigned driskull Dec 6, 2022
@driskull driskull added 1 - assigned Issues that are assigned to a sprint and a team member. and removed 0 - new New issues that need assignment. labels Dec 6, 2022
@driskull driskull changed the title Infinite loop when calling setFocus on new calcite-input inside a modal Infinite loop when calling setFocus on new calcite-input Dec 6, 2022
@eriklharper
Copy link
Contributor

It actually has nothing to do with the modal. If you append the input's to the body it freezes as well.

Could you share a codepen that reproduces this? I can't repro that with code like this (based on your description, assuming a button is wired up to fire this callback):

function addInput() {
      const input = document.createElement("calcite-input");
      document.body.appendChild(input);
      input.setFocus();
    }

@driskull
Copy link
Member

driskull commented Dec 8, 2022

I was wrong, it does have to do with the focus trap but not modal specifically. It seems to fight the focus trap because of that infinite loop it gets into.

here's a reproduction:

https://codepen.io/driskull/pen/JjZzdBN?editors=1010

@driskull
Copy link
Member

driskull commented Dec 8, 2022

If you change the JS to just use a native input it works fine.

@eriklharper
Copy link
Contributor

I was wrong, it does have to do with the focus trap but not modal specifically.

This is my finding as well after investigating.

driskull added a commit that referenced this issue Dec 9, 2022
…ser. #5882 (#5961)

**Related Issue:** #5882

## Summary

- Adds click handler to focus on internal inputs
- Focus handler only emits event
@driskull driskull added 3 - installed Issues that have been merged to master branch and are ready for final confirmation. and removed 1 - assigned Issues that are assigned to a sprint and a team member. labels Dec 9, 2022
@github-actions github-actions bot assigned geospatialem and unassigned eriklharper Dec 9, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Dec 9, 2022

Installed and assigned for verification.

@geospatialem geospatialem added 4 - verified Issues that have been released and confirmed resolved. and removed 3 - installed Issues that have been merged to master branch and are ready for final confirmation. needs triage Planning workflow - pending design/dev review. labels Dec 9, 2022
@geospatialem
Copy link
Member

Verified in beta.668 with the following Codepen using the disableFocusTrap prop.

benelan added a commit that referenced this issue Dec 12, 2022
* master: (55 commits)
  build: update browserslist db (#5986)
  docs: update component READMEs (#5980)
  1.0.0-next.670
  refactor(input-date-picker,date-picker)!: Removing deprecated locale properties (#5977)
  1.0.0-next.669
  refactor(input-date-picker)!: Remove deprecated active property (#5974)
  1.0.0-next.668
  fix(modal, popover): Add `disableFocusTrap` property to toggle focus trapping. (#5965)
  1.0.0-next.667
  refactor(input-time-picker)!: Remove deprecated active property (#5970)
  docs(changelog): fix breaking change indent levels (#5973)
  1.0.0-next.666
  refactor(time-picker)!: Remove deprecated locale property (#5962)
  1.0.0-next.665
  fix(input, input-number, input-text): Fix infinite loop crashing browser. #5882 (#5961)
  test(floating-ui): fix type errors (#5966)
  docs: update component READMEs (#5964)
  1.0.0-next.664
  fix(alert): auto-dismissible retains close button and dismisses timer while a user is hovering over (#5872)
  chore(color-picker): add opacity string (#5959)
  ...
@nwhittaker
Copy link
Contributor Author

@driskull, I'm having trouble with the solution because I'd like to continue trapping focus within the modal. Temporarily disabling the focus trap shifts focus back to the modal's close button when I re-enable the trap: https://codepen.io/nwhittaker-esri/pen/QWBwNxy. Would that be considered a bug?

What is the recommend pattern for using the new disableFocusTrap property to support the reported use-case of setting focus on a new element in the modal? Am I expected to keep it disabled and implement my own focus trap logic instead?

FWIW, I was thinking you'd just call updateContainerElements() on the focus trap whenever the content slot's subtree was mutated which should rebuild the list of tabbable nodes. Any problems with this type of approach?

@driskull
Copy link
Member

FWIW, I was thinking you'd just call updateContainerElements() on the focus trap whenever the content slot's subtree was mutated which should rebuild the list of tabbable nodes. Any problems with this type of approach

Yes, I tried this but it didn't seem to work. I think the focus-trap module has a bug with custom elements. I need to create a repro and open a bug for them.

@driskull
Copy link
Member

Hey Adelheid, for the focusing issue, have you tried using requestAnimationFrame instead of some timeout with a number?

Like:

requestAnimationFrame(() => el.setFocus());

Example: https://codepen.io/benesri/pen/MWBgJBR

@driskull
Copy link
Member

@nwhittaker created issue here: #6140

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4 - verified Issues that have been released and confirmed resolved. ArcGIS Field Apps Issues logged by ArcGIS Field Apps team members. bug Bug reports for broken functionality. Issues should include a reproduction of the bug. p - high Issue should be addressed in the current milestone, impacts component or core functionality regression Issues that are caused by changes in a release, but were working before that.
Projects
None yet
Development

No branches or pull requests

5 participants