我正在编写一个自动完成的自定义组件,作为使用JSF的学习练习2.1.3. 这个想法(这可能很熟悉)是将一些文本输入并输入组件,并显示一个带有匹配值的列表框。这个想法是在输入上有一个keyup javascript事件,它调用jsf.ajax.request()更新组件。到目前为止,我已经有了一个组件,我可以包括:
<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'。通过指定execute:'myauto'解码()方法执行,我可以获得输入值。通过指定render: 'myauto', encode…()方法执行以重新生成html。
这一切都很好,但因为我渲染的父myauto_input每次keyup事件触发时,组件就会失去输入焦点。
如果我指定像render: 'myauto_listbox'这样的东西(我只是真的想重新呈现列表框)问题在于encode…()方法不要执行,因为它们是针对整个定制组件的,而不仅仅是列表框。它将在我重建的encode…()方法之一中包含建议的列表框。
组件扩展了UIInput,我在一个单独的渲染器中生成标记(componentFamily = "javax.faces.Input")在encodeEnd()方法中总是在任何提供的转换器之后运行-尚未实现)。我想从javascript强制聚焦是一个可怕的hack,应该避免。
我有点不确定要去哪里,但我怀疑我所看到的说明我用了错误的方法。如果有人能给我指出正确的方向,我会很感激的div。
我花了一些时间来研究这个问题以及之后失去焦点的一般问题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(), chrome只需要。focus())
所以看起来可怕的黑客拯救了一天。我想过会不会有如果我使用jQuery ajax例程而不是jsf ajax库,有什么区别吗我想这不会有什么区别。