如何在视图中设置初始焦点?

rpl*_*iko 3 sapui5

我在 SAPUI5 应用程序中有一个 Detail 视图,其中包含一个 ID 的输入字段"bestellmenge_tu"。每当调用此视图时,焦点应位于该输入字段上。不幸的是,当在控制器的onInit方法中将焦点设置在字段上时,焦点将被设置,但几毫秒后 UI5 将其拿走并将其转移到详细信息视图的“导航返回”按钮。

通过将 alog.trace()放在输入字段的blur事件上,我发现焦点被一个sap.ui.define.NavContainer._afterTransitionCallback被调用的方法夺走了,该方法被异步调用(window.setTimeout触发器和执行之间的一些s)。该函数只是在视图中查找第一个可聚焦的元素,然后粗暴地将焦点切换到它上面。

我的解决方法是重新定义jQuery.fn.firstFocusableDomRef用于查找“第一个可聚焦元素”的方法:

// DIESE KANONE FUNKTIONIERT
jQuery.fn.firstFocusableDomRef = (function() {
  var _default = jQuery.fn.firstFocusableDomRef;
  return function() {
    var bestellmenge_tu = document.querySelector("input[id$='bestellmenge_tu-inner']");
    if (bestellmenge_tu &&
        bestellmenge_tu.style.display !="none" &&
        bestellmenge_tu.style.visibility != "hidden") return bestellmenge_tu;
    else return _default.apply(this);
  }
})();
Run Code Online (Sandbox Code Playgroud)

但这可能是一个性能问题(querySelector在此后的任何页面加载的DOM 横向期间调用),并且对于所需的效果来说代码太多。

有没有更简单的方法来实现这一目标?

我想到了类似的东西

<mvc:View controllerName="zrt_dispo.view.Detail"...>
  <Page id="detailPage" initialFocus="bestellmenge_tu">  <!-- ID of the element to carry the focus -->
  </Page>
</mvc:view>
Run Code Online (Sandbox Code Playgroud)

Bog*_*ann 6

这是一个工作示例:https : //embed.plnkr.co/wp6yes/

<App autoFocus="false" xmlns="sap.m"> <!-- AND/OR -->
<f:FlexibleColumnLayout autoFocus="false" xmlns:f="sap.f" /> <!-- autoFocus in FCL available since 1.76 -->
Run Code Online (Sandbox Code Playgroud)
{ // 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果你有一个 NavContainer(sap.m.App或 in sap.f.FlexibleColumnLayout),它的直接子节点,又名。NavContainerChild通常是一个视图,可以对导航相关事件做出反应。在我们的例子中,我们应该afterShow根据 API 参考为事件附加一个处理程序:

afterShow事件可用于聚焦另一个元素,前提autoFocus是设置为false[来源]

动画完成后触发事件处理程序。而最重要的是:

每次(与 相比onAfterRendering)当 NavContainer 使该子控件可见时都会触发此事件。

由于sap.ui.core.Controlextends sap.ui.core.Element,每个控件都可以通过focus().


笔记

  • 正如这篇文章中提到,从 Fiori Launchpad (FLP) 启动应用程序的第一个重点是由启动板控制的,目前没有 API 可以改变这种行为。
  • 在 UI5 1.62 及更低版本中,即使使用(请参阅此GitHub 问题),当用户向后导航时focus()onAfterShow单独调用仍会使应用程序将焦点设置在第一个可聚焦元素。因此,需要一个额外的with ms (or ) 来让浏览器知道元素应该被聚焦在调用堆栈的末尾。 autoFocus="false"setTimeout0requestAnimationFrame
    onAfterShow: function() {
      // Only if UI5 version < 1.63:
      setTimeout(() => this.byId("thatControl").focus());
    },
    
    Run Code Online (Sandbox Code Playgroud) 使用commit:6d46cf0,该修复从 1.63 开始可用。