JSF自定义组件失去了关注ajax更新的输入

Ove*_*eer 6 javascript ajax jsf custom-component

我正在编写一个自动完成自定义组件作为JSF 2.1.3的学习练习.这个想法(可能非常熟悉)是输入一些文本和输入组件,并显示一个匹配值的列表框.想法是在输入上有一个keyup javascript事件,它调用jsf.ajax.request()来更新组件.到目前为止,我有一个组件,我可以包括这样:

<mycc:autocomplete id="myauto" searchMethod="#{bean.doSearch}"/>
Run Code Online (Sandbox Code Playgroud)

这会呈现这样的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>
Run Code Online (Sandbox Code Playgroud)

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

jsf.ajax.request(comp, null, {
                 execute: 'myauto',
                 render: 'myauto'
                 });
Run Code Online (Sandbox Code Playgroud)

因为我想用建议列表重建和重新呈现列表框,我重新渲染自定义组件'myauto'.通过指定execute:'myauto',decode()方法执行,我可以获取输入值.通过指定render:'myauto',执行encode ...()方法来重新生成html.

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

如果我指定像render这样的东西:'myauto_listbox'(我真的只想重新渲染列表框)问题是编码...()方法不执行,因为它们是整个自定义组件,而不仅仅是列表框.它将在我重建包含建议的列表框的encode ...()方法之一中.

该组件扩展了UIInput,我在encodeEnd()方法中的单独渲染器(componentFamily ="javax.faces.Input")中生成标记(因此这总是在任何提供的转换器之后运行 - 尚未实现).我想强迫javascript的焦点是一个可怕的黑客,并且要避免.

我有点不确定该去哪里,但我怀疑我所看到的表明我正以某种方式以错误的方式接近这一点.如果有人能够指出我正确的方向,我会非常感激.

Ove*_*eer 1

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

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

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

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

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