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 tag?


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


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

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:


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

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