JSF自定义组件在ajax更新中丢失输入

时间:2022-05-15 20:03:02

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:

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

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

This renders html like this:

这个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>

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

com. co. myajaxrequest () javascript函数keyup完成以下操作:

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.

因此,因为我想要重新构建和重新运行列表框,我将重新呈现定制组件的myauto。通过指定execute:“myauto”,decode()方法执行,我可以得到输入值。通过指定呈现:“myauto”,可以执行encode…()方法来重新生成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.

这很好,但是因为我正在呈现myauto_input组件的父元素,所以每次keyup事件触发时,我都会失去输入焦点。

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.

如果我指定类似于render: 'myauto_listbox'(我只想重新运行列表框)的内容,那么问题是encode…()方法不会执行,因为它们是针对自定义组件的,而不仅仅是列表框。我将在encode…()方法之一中重新构建包含建议的列表框。

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.

该组件扩展了UIInput,我在encodeEnd()方法中在一个独立的渲染器(componentFamily = "javax.faces.Input")中生成标记(因此,它总是在任何提供的转换器之后运行——尚未实现)。我认为,强迫关注javascript是一种可怕的黑客行为,应该避免。

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.

我有点不确定该怎么处理这个问题,但我怀疑我所看到的表明我在以错误的方式处理这个问题。如果有人能给我指出正确的方向,我将非常感激。

1 个解决方案

#1


1  

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').

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

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:

在我的自定义组件的情况下,我(认为我…)必须更新自定义组件本身,它是输入的父元素,因此由于ajax更新,我将会失去焦点,这就是事实。因此,我已经研究了需要做什么来恢复焦点,并且似乎在我的渲染器编码中,我只需要强制地将焦点恢复到输入,但是只有在响应来自jsf.ajax.request的onkeyup事件的POST时才需要这样做。我使用jQuery,仅仅调用.focus()是不够的,因为您还必须将光标位置放在任何现有输入的末尾。下面的代码看起来不错:

<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...)

(注:.focus().focus().click()为IE8所需,仅.focus()为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.

看起来恐怖的黑客拯救了这一天。我想知道如果我使用jQuery ajax例程而不是jsf ajax库是否会有什么不同,但我不认为会有什么不同。

#1


1  

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').

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

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:

在我的自定义组件的情况下,我(认为我…)必须更新自定义组件本身,它是输入的父元素,因此由于ajax更新,我将会失去焦点,这就是事实。因此,我已经研究了需要做什么来恢复焦点,并且似乎在我的渲染器编码中,我只需要强制地将焦点恢复到输入,但是只有在响应来自jsf.ajax.request的onkeyup事件的POST时才需要这样做。我使用jQuery,仅仅调用.focus()是不够的,因为您还必须将光标位置放在任何现有输入的末尾。下面的代码看起来不错:

<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...)

(注:.focus().focus().click()为IE8所需,仅.focus()为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.

看起来恐怖的黑客拯救了这一天。我想知道如果我使用jQuery ajax例程而不是jsf ajax库是否会有什么不同,但我不认为会有什么不同。