我正在编写一个自定义的自动完成组件,作为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'
});
所以,因为我想要使用建议列表重新构建和重新渲染listbox,所以我正在重新渲染自定义组件'myauto'。通过指定execute: 'myauto',decode()方法执行并且我可以获取输入值。通过指定render: 'myauto',encode...()方法执行以重新生成html。
这一切都很好,但是因为我正在渲染myauto_input组件的父级,每次keyup事件触发时都会失去输入焦点。
如果我指定类似于render: 'myauto_listbox'的内容(毕竟我只想重新渲染列表框),问题在于encode...()方法不执行,因为它们是针对整个自定义组件而不仅仅是列表框。而我重建包含建议的列表框就在其中一个encode...()方法中。
该组件扩展了UIInput并在encodeEnd()方法中生成标记(componentFamily = "javax.faces.Input")。我假设从JavaScript强制聚焦是可怕的hack,应该避免使用。
我有点不确定该怎么做,但我认为我看到的情况表明我在某种程度上错误地处理了这个问题。如果有人能够指引我正确的方向,我将非常感激。