JSF 自定义组件在 ajax 更新时失去输入焦点

发布于 2024-11-30 21:07:56 字数 1445 浏览 0 评论 0原文

我正在编写一个自动完成自定义组件作为 JSF 的学习练习 2.1.3.这个想法(可能很熟悉)是在其中输入一些文本 和输入组件并呈现一个具有匹配值的列表框。这个想法是 在调用 jsf.ajax.request() 的输入上有一个 keyup javascript 事件 来更新组件。到目前为止,我已经有了一个可以包含在内的组件 这:

<mycc:autocomplete id="myauto" searchMethod="#{bean.doSearch}"/>

这会像这样呈现 html:

<span id="myauto">
  <input type="text" id="myauto_input" name="myauto_input"
    onkeyup="com.myco.ajaxRequest(this, event)"/>
  <select id="myauto_listbox" name="myauto_listbox">
    <option value="1st">First</option>
    <option value="2nd">Second</option>
  </select>
</span>

com.myco.ajaxRequest() javascript 函数(keyup)执行此操作:

jsf.ajax.request(comp, null, {
                 execute: 'myauto',
                 render: 'myauto'
                 });

所以因为我想使用建议重建并重新呈现列表框 列表中,我正在重新渲染自定义组件“myauto”。通过指定执行: 'myauto' 执行decode() 方法,我可以获得输入值。经过 指定 render: 'myauto' 执行encode...() 方法来重新生成 html。

这一切都很好,但是因为我正在渲染 myauto_input 的父级 每次 keyup 事件触发时,我都会失去输入焦点。

如果我指定类似 render: 'myauto_listbox' (我真的只想 毕竟重新渲染列表框)问题是encode...() 方法 不要执行,因为它们是针对整个自定义组件的,而不仅仅是 列表框。它将位于我重建的编码...() 方法之一中 包含建议的列表框。

该组件扩展了 UIInput,我在单独的渲染器中生成标记 (componentFamily = "javax.faces.Input") 在encodeEnd()方法中(所以这个 始终在任何提供的转换器之后运行 - 尚未实现)。我想 强制焦点从 javascript 转移是一种可怕的黑客行为,应该避免。

我有点不确定该去哪里,但我怀疑我所看到的 表明我以某种错误的方式处理这个问题。如果有人 足以为我指明正确的方向,我将不胜感激 它。

I'm writing an autocomplete custom component as a learning exercise with JSF
2.1.3. The idea (which is probably pretty familiar) is to enter some text into
and input component and present a list box with matching values. The idea is
to have a keyup javascript event on the input which calls jsf.ajax.request()
to update the component. So far I've got a component which I can include like
this:

<mycc:autocomplete id="myauto" searchMethod="#{bean.doSearch}"/>

This renders html like this:

<span id="myauto">
  <input type="text" id="myauto_input" name="myauto_input"
    onkeyup="com.myco.ajaxRequest(this, event)"/>
  <select id="myauto_listbox" name="myauto_listbox">
    <option value="1st">First</option>
    <option value="2nd">Second</option>
  </select>
</span>

The com.myco.ajaxRequest() javascript function (keyup) does this:

jsf.ajax.request(comp, null, {
                 execute: 'myauto',
                 render: 'myauto'
                 });

So because I want to rebuild and rerender the listbox with the suggestions
list, I'm re-rendering the custom component 'myauto'. By specifying execute:
'myauto' the decode() method executes and I can get the input value. By
specifying render: 'myauto' the encode...() methods execute to regenerate
the html.

This is all fine but because I'm rendering the parent of the myauto_input
component I lose input focus every time the keyup event fires.

If I specify something like render: 'myauto_listbox' (I only really want to
rerender the listbox after all) the problem is that the encode...() methods
don't execute, because they're for the custom component as a whole, not just
the listbox. And it would be in one of the encode...() methods that I rebuild
the listbox containing the suggestions.

The component extends UIInput and I generate markup in a separate renderer
(componentFamily = "javax.faces.Input") in the encodeEnd() method (so this
always runs after any supplied converter - not yet implemented). I suppose
that forcing focus from javascript is a horrible hack and to be avoided.

I'm a bit unsure where to go with this, but I suspect that what I'm seeing
indicates that I'm approaching this in the wrong way somehow. If anyone
would be good enough to point me in the right direction I'd greatly appreciate
it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

初与友歌 2024-12-07 21:07:56

我花了一些时间研究这个问题以及之后失去焦点的一般问题
ajax 更新相当常见,Jim Driscoll 的 博客 中对此进行了描述(请参阅
“保持专注”)。

对于我的自定义组件,我(认为我......)必须更新自定义组件
本身是输入的父级,所以我将由于以下原因而失去焦点
ajax更新,就是这样。因此我已经研究了需要做什么
完成恢复焦点,似乎在我的渲染器编码中我只需要
强制将焦点恢复到输入,但仅当响应 jsf.ajax.request 从 onkeyup 事件发送的 POST 时。我使用 jQuery 并且只调用 .focus() 不是
足够了,因为您还必须将光标位置移动到任何现有的末尾
输入。下面的代码似乎工作正常:(

<script>
  jQuery(function($){var cid='#myauto_input';$(cid).focus().focus().click();$(cid).val($(cid).val());});
</script>

注意:IE8需要.focus().focus().click(),只有.focus()适用于chrome...)

所以看起来可怕的黑客已经拯救了世界。我确实想知道是否会有
如果我使用 jQuery ajax 例程而不是 jsf ajax 库,会有什么区别,但是
我认为这不会有任何区别。

I've spent some time looking into this and the general issue of losing focus after
an ajax update is fairly common and is described in Jim Driscoll's blog (see
'Keeping Focus').

In the case of my custom component I (think I...) have to update the custom component
itself which is the parent of the input, so I'm going to lose focus as a result of the
ajax update, and that's just the way it is. As such I've looked at what needs to be
done to restore focus, and it seems that in my renderer encode I simply have to
forcibly restore focus to the input, but only when responding to the POST sent from the onkeyup event by jsf.ajax.request. I use jQuery and just calling .focus() isn't
enough because you also have to get the cursor position to the end of any existing
input. This code below seems to work ok:

<script>
  jQuery(function($){var cid='#myauto_input';$(cid).focus().focus().click();$(cid).val($(cid).val());});
</script>

(note: .focus().focus().click() required for IE8, just .focus() works on chrome...)

So it looks like the horrible hack has saved the day. I did wonder if there would be
any difference if I used the jQuery ajax routines rather than the jsf ajax library but
I don't suppose it would make any difference.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文