Skip to main content

Keeping focus

Posted by driscoll on August 11, 2009 at 10:56 AM PDT


A recent user question, which has been repeated enough times to warrant a blog posting. In short: Why am I losing focus when I use the <f:ajax> tag?


Let's imagine you have a form, with two input fields and two output fields:

<pre>
   1 &lt;h:form&gt;
   2 &lt;f:ajax event=&quot;blur&quot; render=&quot;@form&quot;&gt;
   3   &lt;h:inputText id=&quot;onein&quot; value=&quot;#{bean.one}&quot;&gt;
   4   &lt;/h:inputText&gt;
   5   &lt;h:outputText id=&quot;oneout&quot; value=&quot;#{bean.one}&quot; /&gt;
   6   &lt;h:inputText id=&quot;twoin&quot; value=&quot;#{bean.two}&quot;&gt;
   7   &lt;/h:inputText&gt;
   8   &lt;h:outputText id=&quot;twoout&quot; value=&quot;#{bean.two}&quot; /&gt;
   9 &lt;/f:ajax&gt;
  10 &lt;h:commandButton value=&quot;Submit&quot; /&gt;
  11 &lt;/h:form&gt;
</pre>

You enter data in field one, tab to field two, and bam! the focus on field two is lost.


Why?


When you tabbed out of field one, you generated a blur event. This calls an Ajax request, which updates the entire form. That, in turn, removes and re-adds all of the elements in that form - including field 2. With that field (momentarily) gone, the focus is lost.


So, how to deal with this?


Simple rule: Don't replace the parent element of the element whose focus you want to keep. There's also a simple corollary: Don't update stuff you don't have to.


Here's the changed markup that works:

<pre>
   1 &lt;h:form&gt;
   2   &lt;h:inputText id=&quot;onein&quot; value=&quot;#{bean.one}&quot;&gt;
   3     &lt;f:ajax render=&quot;oneout&quot;/&gt;
   4   &lt;/h:inputText&gt;
   5   &lt;h:outputText id=&quot;oneout&quot; value=&quot;#{bean.one}&quot; /&gt;
   6   &lt;h:inputText id=&quot;twoin&quot; value=&quot;#{bean.two}&quot;&gt;
   7     &lt;f:ajax render=&quot;twoout&quot;/&gt;
   8   &lt;/h:inputText&gt;
   9   &lt;h:outputText id=&quot;twoout&quot; value=&quot;#{bean.two}&quot; /&gt;
  10 &lt;h:commandButton value=&quot;Submit&quot; /&gt;
  11 &lt;/h:form&gt;
</pre>

Note that you could also say render="onein oneout twoout twoin" and it will still work because you aren't updating the parent (the h:form) - even though you're updating the field that has the focus.

Questions? Ask below.

Related Topics >>