I have a Detail view in an SAPUI5 app which contains a single input field with ID \"bestellmenge_tu\"
. Whenever this view is called, the focus should be on that
The NavContainer
has a property autoFocus. App
is a descendant of NavContainer
so it has that property too.
The help (as linked above) states the following:
Determines whether the initial focus is set automatically on first rendering and after navigating to a new page. This is useful when on touch devices the keyboard pops out due to the focus being automatically set on an input field. If necessary the "afterShow" event can be used to focus another element.
Default value is true.
Here is a working example: https://embed.plnkr.co/wp6yes/
<App autoFocus="false">
In the controller of the target view:
onInit: function() {
this.attachAfterShow(this.onAfterShow);
},
attachAfterShow: function(onAfterShow) {
this._afterShowDelegate = { onAfterShow };
this.getView().addEventDelegate(this._afterShowDelegate, this);
},
onAfterShow: function() {
this.byId("thatControl").focus();
},
onExit: function() { // detach delegates
this.getView().removeEventDelegate(this._afterShowDelegate);
this._afterShowDelegate = null;
},
If you have a NavContainer (sap.m.App or in sap.f.FlexibleColumnLayout), its direct child, aka. NavContainerChild which is usually a View, can react to navigation related events. In our case, we should attach a handler to the event afterShow according to the API reference:
The
afterShow
event can be used to focus another element, only ifautoFocus
is set tofalse
.[source]
The event handler is fired after the animation is finished. And most importantly:
This event is fired every time (in contrast to
onAfterRendering
) when the NavContainer has made this child control visible.
Since sap.ui.core.Control
extends sap.ui.core.Element
, every control can receive the focus via focus().
focus()
in onAfterShow
alone would still make the app set the focus on the first focusable element when the user navigates back, even with autoFocus="false"
(See this GitHub issue). Therefore, an additional setTimeout with 0
ms (or requestAnimationFrame) is needed in order to let the browser know that the element should be focused at the end of the call stack.
onAfterShow: function() {
setTimeout(() => this.byId("thatControl").focus());
},
With this commit, which is available as of 1.63, that workaround is no longer required.