1
votes

When I do a reRender via a4j:support of Richfaces (3.3.3) on a h:selectOneRadio, I have a strange behavior (not every time).

Here is my xhtml section with the h:selectOneRadio:

<h:selectOneRadio id="toto" value="#controller.toto}" >
   <f:selectItem itemLabel="#{bundle['oui']}"
   itemValue="#{true}" />
   <f:selectItem itemLabel="#{bundle['non']}"
   itemValue="#{false}" />
</h:selectOneRadio>
<rich:message for="toto" />

When I go in a browser I get this html code:

<table id="formulaire:toto" >
<tbody>
<tr>
<td>
<input id="formulaire:toto:0" type="radio" onchange="A4J.AJAX.Submit('formulaire',event,{'control':this,'similarityGroupingId':'formulaire:support','parameters':{'ajaxSingle':'formulaire:toto','formulaire:support':'formulaire:support'} } )" value="true" name="formulaire:toto">
<label for="formulaire:toto:0"> oui</label>
</td>
<td>
<input id="formulaire:toto:1" type="radio" onchange="A4J.AJAX.Submit('formulaire',event,{'control':this,'similarityGroupingId':'formulaire:support','parameters':{'ajaxSingle':'formulaire:toto','formulaire:support':'formulaire:support'} } )" value="false" name="formulaire:toto" checked="checked">
<label for="formulaire:toto:1"> non</label>
</td>
</tr>
</tbody>
</table>

Everything is fine.

But when this one is reRender by another component, the html changes and the first radio element is out of the table:

<input type="radio" onchange="A4J.AJAX.Submit('formulaire',event,{'control':this,'similarityGroupingId':'formulaire:support','parameters':{'ajaxSingle':'formulaire:toto','formulaire:support':'formulaire:support'} } )" value="true" id="formulaire:toto:0" name="formulaire:toto" checked="checked">
<label for="formulaire:toto:0"> oui</label>
<table id="formulaire:toto">
<tbody>
<tr>
<td>
    <input type="radio" onchange="A4J.AJAX.Submit('formulaire',event,{'control':this,'similarityGroupingId':'formulaire:support','parameters':{'ajaxSingle':'formulaire:toto','formulaire:support':'formulaire:support'} } )" value="false" id="formulaire:toto:1" name="formulaire:toto"><label for="formulaire:toto:1"> non</label>
</td>
</tr>
</tbody>
</table>

It's a very strange behavior and it breaks my style.

Why the reRender breaks the html code ?

Thanks.

2
Which component are you rerendering? - user1983983
I reRender the h:selectOneRadio from another component like this: <h:selectOneRadio value="#{controller.titi}" > <f:selectItem itemLabel="#{bundle['oui']}" itemValue="#{true}" /> <f:selectItem itemLabel="#{bundle['non']}" itemValue="#{false}" /> <a4j:support event="onclick" ajaxSingle="true" id="support" reRender="toto" /> </h:selectOneRadio> - Kiva

2 Answers

1
votes

After many searchs, the bug comes from neko.

To optimize performances, I change the xml parse (tiny by default) by neko and this one can break the html.

0
votes

RichFaces 3 AJAX responses are served with the Content-Type: text/xml header. They are therefore supposed to be valid XML and are parsed as such on the browser side by the RichFaces JavaScript client code.

On the other hand, the HTML generated from templates is not required to be valid XML, so when RichFaces re-renders a fragment of a template, it tidies it up by default with the Tidy parser to avoid parsing issues on the client side.

It is often recommended to replace the Tidy parser with NekoHTML for better performance. However, NekoHTML can go too far in the tidying process and break some RichFaces/JSF components, mostly those based on the HTML element.

For instance, since version 1.9.13, NekoHTML automatically adds TBODY around TR nested directly within TABLE. Downgrading to the 5.5 year old version 1.9.12 reverts this behaviour and fixes re-rendering of components. But this is not an option IMHO as lots of issues have been fixed over the last years.

From my experience, a better way to gain performance and avoid those issues is to :

  1. ensure the re-rendered parts of your templates are valid XML

  2. drop the tidying parsers

Corresponding web.xml snippet:

<context-param>
  <param-name>org.ajax4jsf.xmlparser.ORDER</param-name>
  <param-value>NONE</param-value>
</context-param>

To avoid breaking too much at once, the transition can be managed on a page by page basis using patterns:

<context-param>
  <param-name>org.ajax4jsf.xmlparser.ORDER</param-name>
  <param-value>TIDY,NEKO,NONE</param-value>
</context-param>
<context-param>
  <param-name>org.ajax4jsf.xmlparser.TIDY</param-name>
  <param-value>/pages/tidy/.*\.xhtml</param-value>
</context-param>
<context-param>
  <param-name>org.ajax4jsf.xmlparser.NEKO</param-name>
  <param-value>/pages/neko/.*\.xhtml</param-value>
</context-param>