How is your experience with the OutSystems Community?
13
Views
4
Comments
Solved by AI
Popup auto-focusing on intereactable element when opened
Application Type
Mobile
Service Studio Version
11.55.84 (Build 65120)

I came across a strange behavior when it comes to popups that are scroll-able and that contain certain elements in them, such as buttons/links or inputs, for example.

Context:

I have this setup in my css. Very simple overwrites of the existing outsystems popup classes:

The business requirement needs for popups to grow up to a certain height, as its content grows, and past this max-height, the popup should be scroll-able, which is why I added the "overflow-y: scroll" rule.

This works fine, and the popup does become scroll-able when it needs to.

For extra content, the popup will be used with a separate Block built with a title, description, and actions placeholders.

The issue comes when a particular popup, with enough content that it does become scroll-able, contains elements like buttons. When such elements are present in the popup, once the popup is opened, these elements are getting focused without me programmatically setting its focus state whatsoever.

For example, this popup should be opened like so:

But instead, it's opening in this state (completely scrolled to the bottom):

If I run "document.activeElement" as the popup opens, it does indeed return that this link at the bottom is being automatically focused, which explains why the popup opens being scrolled all the way to the bottom.

However, I did not add any code in my app to make this element be focused once the popup opens, this is happening automatically. I even tested on a personal environment in a fresh new app, and the behavior is the exact same.

I tried to add a a dummy expression on the top of the popup (with a tabindex=-1 property), and target it with document.querySelector('.dummy').focus() once it opens, in order to force focus on this element, but it doesn't seem to work. It only worked by doing it manually in the browser console, which is obviously not a solution.

Is there a way to prevent this autofocus behavior from happening?

2023-12-26 10-35-28
OutSystems Neo
Staff
Solution by AI
AI Generated

In mobile (and Reactive Web) there’s no PopupEditor widget and no OnReady event for a popup, so you need a slightly different approach. The underlying issue is the same, though: a focusable element inside your scrollable popup is getting focus automatically, and the container scrolls to make it visible.

You basically have two options:


In mobile / Reactive, your “popup” is typically:

  • A Block or Container shown/hidden with a boolean, or
  • A Modal/Dialog pattern from OutSystems UI.

In both cases you can still use SetFocus; you just have to call it from the client action that opens the popup, or from a small “init” client action inside the popup block, instead of an OnReady.

Steps

  1. Add a focusable element at the top of the popup content
    For example:

    • A Button or Link,
    • An Input, or
    • A small dummy Input with tabindex="-1" if you don’t want it in the normal tab order.
  2. Give that widget a Name, so you can reference its Id.

  3. In the client action that you use to open the popup (e.g. on Click of the “Open popup” button):

    • First set your boolean that shows the popup to True (or call the Modal’s Show action).
    • Immediately after that, call SetFocus and pass the top element’s Id.

    Example flow (mobile / Reactive):

    • OpenPopup client action:
      1. Assign → ShowPopup = True
      2. SetFocus (from OutSystems UI) → WidgetId = PopupTopElement.Id

    If the popup content is complex and you see SetFocus happening too early, wrap it in a tiny delay using JavaScript or a separate client action triggered by a boolean, but in many cases calling SetFocus right after opening is enough. OutSystems UI team explicitly suggests this approach as a workaround for unwanted autofocus in mobile components DropdownSearch and DropdownTags receive autofocus when entering a screen.

  4. Make sure no other focus operation runs after that:

    • No widgets with autofocus extended property,
    • No JS in the screen that calls focus() on another element,
    • No additional SetFocus in other logic.

This way, you “win” the focus race and keep the scroll at the top of the popup.


2. Reduce or neutralize autofocus inside the popup (if you can’t control focus timing)

On mobile, some UI patterns (e.g. DropdownSearch/Tags) still grab focus automatically due to the underlying library, even after fixes for desktop DropdownSearch and DropdownTags receive autofocus when entering a screen. Similar behavior can happen with inputs/buttons in your popup.

If you can’t reliably push focus to the top element, you can try to:

  1. Avoid patterns that auto-open or auto-focus inside the popup (DropdownSearch/Tags, some custom JS widgets).
  2. Remove any autofocus extended property from inputs.
  3. If a specific OutSystems UI pattern is known to autofocus on mobile, consider:
    • Disabling its popup / special view if that’s what is causing focus (as suggested for DropdownSearch via DropdownTogglePopup), or
    • Replacing it with a simpler widget that doesn’t manage focus itself.

This doesn’t give you perfect control, but can reduce the chances that an element at the bottom is focused first.


Why your document.querySelector('.dummy').focus() works only in the console

In mobile / Reactive:

  • Your JS likely runs before the popup content is in the DOM or visible.
  • The browser/library then moves focus again to the “real” interactive element (button/link) after your dummy one is focused.
  • When you run the same command manually in the console, it’s after all rendering and autofocus have finished, so your focus sticks.

That’s exactly why OutSystems UI recommends using SetFocus with the right timing in the screen lifecycle as the workaround, and not just arbitrary JS DropdownSearch and DropdownTags receive autofocus when entering a screen.


In short

Even in mobile (no Popup OnReady):

  1. Show your popup (set boolean / call Modal Show).
  2. Immediately call SetFocus to a widget at the top of the popup.
  3. Remove any competing autofocus logic inside the popup.

That’s the most practical way to prevent the bottom button/link from being auto-focused and the popup from opening scrolled to the bottom.

This answer was AI-generated. Please read it carefully and use the forums for clarifications
2023-12-26 10-35-28
OutSystems Neo
Staff
AI Generated

This autofocus + scroll-to-bottom behavior is coming from the browser’s native focus handling combined with the popup being scrollable, not from anything specific you coded in the app. Because the popup is part of the same document as the page (OutSystems Traditional Web popup, or a custom modal), when it opens:

  • The browser keeps focus where it was before (or moves it to the first focusable element it finds).
  • If that focused element is inside the popup and below the fold, the container scrolls to bring that element into view.
  • With overflow-y: scroll on the popup container, the browser will happily scroll it until the focused control is visible—hence the popup opens already scrolled to the bottom when the last button/link gets focus.

You’re basically seeing the same accessibility behavior as when you tab into a long form: the viewport (or scrollable container) moves to ensure the focused element is visible.

To control this in OutSystems, you have to explicitly manage focus when the popup opens. The key point is when you call focus() / SetFocus:

  • It must run after the popup content is rendered and visible.
  • It must target a focusable element at the top of the popup.
  • It must be the last thing that affects focus when opening.

Below are approaches that work well in OutSystems O11.


1. Use OutSystemsUI SetFocus on Popup OnReady (Traditional Web)

OutSystemsUI provides a client action SetFocus exactly for this kind of problem. When using the Popup Editor / Popup Widget:

  1. Inside the popup content, add a focusable element at the top:

    • A button or link; or
    • A hidden-but-focusable element (e.g. an input with tabindex="-1").
  2. Give that widget a known Name (so it has a predictable ID).

  3. In the popup’s OnReady client action:

    • Add the SetFocus action.
    • Set WidgetId to the ID of that top element.

Example:

  • Top element in the popup:
    • A simple Link or Button placed at the very top inside the popup container.
  • OnReady of popup:
    • SetFocus → WidgetId = MyTopLink.Id.

This forces the initial focus into the top of the popup right after it is rendered, instead of letting the browser pick a focusable element at the bottom. That is essentially the same solution described in the “Tab Navigation does not transfer focus to Popup” topic, just adapted to your case Tab Navigation does not transfer focus to Popup unless I click inside.


2. If you’re using pure CSS modals (not Popup Editor), still use SetFocus or JS

If this popup is a custom modal with your CSS (.popup-dialog, .popup-backdrop) instead of the built‑in Popup Editor:

  • Make sure you have a boolean that controls the popup visibility.
  • After you set that boolean to True (open popup), you need to run a client action that:
    1. Waits until the popup is rendered (OnReady of the popup block is best).
    2. Calls SetFocus on a top element.

Why your JS focus() attempt failed

You mentioned:

“I tried to add a dummy expression at the top with tabindex=-1 and run document.querySelector('.dummy').focus() once it opens, but it doesn’t seem to work. It only worked from the browser console.”

Typical reasons in OutSystems:

  • The JS runs before the popup content is actually in the DOM.
  • The dummy element isn’t really focusable (e.g. an <span> with tabindex="-1" will accept focus() but is then immediately overridden by the browser focusing some other element).
  • Another focus operation runs after yours (e.g. a widget with autofocus, an input’s extended property, or a UI script).

To fix that with JS (if needed):

  1. Put the dummy element as a <button> or <a> or <input> at the top, with either:
    • tabindex="0" so it is part of the normal tab order, or
    • tabindex="-1" if you only want it to be focused programmatically.
  2. Trigger focus() after the popup is visible, for example using a small timeout in an OnReady JS snippet:
    setTimeout(function() {
      var el = document.querySelector('.dummy');
      if (el) el.focus();
    }, 0);
    

But in O11, it’s cleaner to use SetFocus instead of custom JS, because it’s designed to run at the correct time in the client lifecycle focus on an input field when opening the popup.


3. Avoid extra autofocus sources in the popup

Check the elements inside the popup for anything that might be stealing focus:

  • Inputs or widgets with an autofocus extended property.
  • Any JS libraries that automatically focus the first or last input.
  • SetFocus called somewhere else (e.g. in the main screen OnReady) after opening the popup.

Make sure the only focus‑setting logic that runs when the popup opens is the SetFocus for your chosen top element.


4. Accessibility note (tabbing behind popup)

Once you start managing focus in a scrollable popup, it’s also good practice to prevent tabbing into elements “behind” the popup while it’s open. On the forums people use:

This doesn’t directly fix your scroll problem, but it keeps keyboard navigation consistent.


Summary / Concrete fix for your case

  1. Add a top focus target inside .popup-dialog (e.g. a Link or hidden input at the top of the popup content).
  2. Use OutSystemsUI SetFocus in the popup’s OnReady to focus that element when the popup opens.
  3. Ensure no other element in the popup has an autofocus or a competing SetFocus.
  4. Optionally, use tabindex ordering to control keyboard navigation inside the popup, but SetFocus is what will prevent the initial scroll-to-bottom.

That will override the browser’s automatic focusing of a button/link near the bottom and keep your scrollable popup opening at the top, in the state you want.

This answer was AI-generated. Please read it carefully and use the forums for clarifications
2023-12-26 10-35-28
OutSystems Neo
Staff
AI Generated

This autofocus + scroll-to-bottom behavior is coming from the browser’s native focus handling combined with the popup being scrollable, not from anything specific you coded in the app. Because the popup is part of the same document as the page (OutSystems Traditional Web popup, or a custom modal), when it opens:

  • The browser keeps focus where it was before (or moves it to the first focusable element it finds).
  • If that focused element is inside the popup and below the fold, the container scrolls to bring that element into view.
  • With overflow-y: scroll on the popup container, the browser will happily scroll it until the focused control is visible—hence the popup opens already scrolled to the bottom when the last button/link gets focus.

You’re basically seeing the same accessibility behavior as when you tab into a long form: the viewport (or scrollable container) moves to ensure the focused element is visible.

To control this in OutSystems, you have to explicitly manage focus when the popup opens. The key point is when you call focus() / SetFocus:

  • It must run after the popup content is rendered and visible.
  • It must target a focusable element at the top of the popup.
  • It must be the last thing that affects focus when opening.

Below are approaches that work well in OutSystems O11.


1. Use OutSystemsUI SetFocus on Popup OnReady (Traditional Web)

OutSystemsUI provides a client action SetFocus exactly for this kind of problem. When using the Popup Editor / Popup Widget:

  1. Inside the popup content, add a focusable element at the top:

    • A button or link; or
    • A hidden-but-focusable element (e.g. an input with tabindex="-1").
  2. Give that widget a known Name (so it has a predictable ID).

  3. In the popup’s OnReady client action:

    • Add the SetFocus action.
    • Set WidgetId to the ID of that top element.

Example:

  • Top element in the popup:
    • A simple Link or Button placed at the very top inside the popup container.
  • OnReady of popup:
    • SetFocus → WidgetId = MyTopLink.Id.

This forces the initial focus into the top of the popup right after it is rendered, instead of letting the browser pick a focusable element at the bottom. That is essentially the same solution described in the “Tab Navigation does not transfer focus to Popup” topic, just adapted to your case Tab Navigation does not transfer focus to Popup unless I click inside.


2. If you’re using pure CSS modals (not Popup Editor), still use SetFocus or JS

If this popup is a custom modal with your CSS (.popup-dialog, .popup-backdrop) instead of the built‑in Popup Editor:

  • Make sure you have a boolean that controls the popup visibility.
  • After you set that boolean to True (open popup), you need to run a client action that:
    1. Waits until the popup is rendered (OnReady of the popup block is best).
    2. Calls SetFocus on a top element.

Why your JS focus() attempt failed

You mentioned:

“I tried to add a dummy expression at the top with tabindex=-1 and run document.querySelector('.dummy').focus() once it opens, but it doesn’t seem to work. It only worked from the browser console.”

Typical reasons in OutSystems:

  • The JS runs before the popup content is actually in the DOM.
  • The dummy element isn’t really focusable (e.g. an <span> with tabindex="-1" will accept focus() but is then immediately overridden by the browser focusing some other element).
  • Another focus operation runs after yours (e.g. a widget with autofocus, an input’s extended property, or a UI script).

To fix that with JS (if needed):

  1. Put the dummy element as a <button> or <a> or <input> at the top, with either:
    • tabindex="0" so it is part of the normal tab order, or
    • tabindex="-1" if you only want it to be focused programmatically.
  2. Trigger focus() after the popup is visible, for example using a small timeout in an OnReady JS snippet:
    setTimeout(function() {
      var el = document.querySelector('.dummy');
      if (el) el.focus();
    }, 0);
    

But in O11, it’s cleaner to use SetFocus instead of custom JS, because it’s designed to run at the correct time in the client lifecycle focus on an input field when opening the popup.


3. Avoid extra autofocus sources in the popup

Check the elements inside the popup for anything that might be stealing focus:

  • Inputs or widgets with an autofocus extended property.
  • Any JS libraries that automatically focus the first or last input.
  • SetFocus called somewhere else (e.g. in the main screen OnReady) after opening the popup.

Make sure the only focus‑setting logic that runs when the popup opens is the SetFocus for your chosen top element.


4. Accessibility note (tabbing behind popup)

Once you start managing focus in a scrollable popup, it’s also good practice to prevent tabbing into elements “behind” the popup while it’s open. On the forums people use:

This doesn’t directly fix your scroll problem, but it keeps keyboard navigation consistent.


Summary / Concrete fix for your case

  1. Add a top focus target inside .popup-dialog (e.g. a Link or hidden input at the top of the popup content).
  2. Use OutSystemsUI SetFocus in the popup’s OnReady to focus that element when the popup opens.
  3. Ensure no other element in the popup has an autofocus or a competing SetFocus.
  4. Optionally, use tabindex ordering to control keyboard navigation inside the popup, but SetFocus is what will prevent the initial scroll-to-bottom.

That will override the browser’s automatic focusing of a button/link near the bottom and keep your scrollable popup opening at the top, in the state you want.

This answer was AI-generated. Please read it carefully and use the forums for clarifications
2021-04-09 12-35-11
Tiago Babo
This is not a Traditional Web application, but a mobile application. There's no OnReady event for the popup.
2023-12-26 10-35-28
OutSystems Neo
Staff
Solution by AI
AI Generated

In mobile (and Reactive Web) there’s no PopupEditor widget and no OnReady event for a popup, so you need a slightly different approach. The underlying issue is the same, though: a focusable element inside your scrollable popup is getting focus automatically, and the container scrolls to make it visible.

You basically have two options:


In mobile / Reactive, your “popup” is typically:

  • A Block or Container shown/hidden with a boolean, or
  • A Modal/Dialog pattern from OutSystems UI.

In both cases you can still use SetFocus; you just have to call it from the client action that opens the popup, or from a small “init” client action inside the popup block, instead of an OnReady.

Steps

  1. Add a focusable element at the top of the popup content
    For example:

    • A Button or Link,
    • An Input, or
    • A small dummy Input with tabindex="-1" if you don’t want it in the normal tab order.
  2. Give that widget a Name, so you can reference its Id.

  3. In the client action that you use to open the popup (e.g. on Click of the “Open popup” button):

    • First set your boolean that shows the popup to True (or call the Modal’s Show action).
    • Immediately after that, call SetFocus and pass the top element’s Id.

    Example flow (mobile / Reactive):

    • OpenPopup client action:
      1. Assign → ShowPopup = True
      2. SetFocus (from OutSystems UI) → WidgetId = PopupTopElement.Id

    If the popup content is complex and you see SetFocus happening too early, wrap it in a tiny delay using JavaScript or a separate client action triggered by a boolean, but in many cases calling SetFocus right after opening is enough. OutSystems UI team explicitly suggests this approach as a workaround for unwanted autofocus in mobile components DropdownSearch and DropdownTags receive autofocus when entering a screen.

  4. Make sure no other focus operation runs after that:

    • No widgets with autofocus extended property,
    • No JS in the screen that calls focus() on another element,
    • No additional SetFocus in other logic.

This way, you “win” the focus race and keep the scroll at the top of the popup.


2. Reduce or neutralize autofocus inside the popup (if you can’t control focus timing)

On mobile, some UI patterns (e.g. DropdownSearch/Tags) still grab focus automatically due to the underlying library, even after fixes for desktop DropdownSearch and DropdownTags receive autofocus when entering a screen. Similar behavior can happen with inputs/buttons in your popup.

If you can’t reliably push focus to the top element, you can try to:

  1. Avoid patterns that auto-open or auto-focus inside the popup (DropdownSearch/Tags, some custom JS widgets).
  2. Remove any autofocus extended property from inputs.
  3. If a specific OutSystems UI pattern is known to autofocus on mobile, consider:
    • Disabling its popup / special view if that’s what is causing focus (as suggested for DropdownSearch via DropdownTogglePopup), or
    • Replacing it with a simpler widget that doesn’t manage focus itself.

This doesn’t give you perfect control, but can reduce the chances that an element at the bottom is focused first.


Why your document.querySelector('.dummy').focus() works only in the console

In mobile / Reactive:

  • Your JS likely runs before the popup content is in the DOM or visible.
  • The browser/library then moves focus again to the “real” interactive element (button/link) after your dummy one is focused.
  • When you run the same command manually in the console, it’s after all rendering and autofocus have finished, so your focus sticks.

That’s exactly why OutSystems UI recommends using SetFocus with the right timing in the screen lifecycle as the workaround, and not just arbitrary JS DropdownSearch and DropdownTags receive autofocus when entering a screen.


In short

Even in mobile (no Popup OnReady):

  1. Show your popup (set boolean / call Modal Show).
  2. Immediately call SetFocus to a widget at the top of the popup.
  3. Remove any competing autofocus logic inside the popup.

That’s the most practical way to prevent the bottom button/link from being auto-focused and the popup from opening scrolled to the bottom.

This answer was AI-generated. Please read it carefully and use the forums for clarifications
Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.