I'm trying to implement a page that shows/hides elements based on the results of a backing bean method which is triggered by the key up event on an input. What I've written is behaving quite unexpectedly - the content inside my panelGroup does not change at all after page load, and instead a wild span is appearing at the top of the page containing the content I expected to be displayed in my outputText elements. This is a legacy application running on JSF 1.2 and richfaces 3.3, so its possible that this functionality might not be available (hinted at here). I also apologize for the use of tables, but unfortunately refactoring this big old app to use proper layout with css/divs is outside the scope of this feature request.
Here is my example jstl template which illustrates the problem. The "string1/2 reversed" outputpanels should only show if the string length is greater than 5, and the text in the outputText elements should be updated while typing in the inputs. Instead, the outputPanels stay static, and a new span is created above the table.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<head>
<title>ajax test</title>
</head>
<body>
<h:panelGroup id="wrapper">
<a4j:keepAlive beanName="AjaxTestBacking" />
<p />
<h:form>
<table>
<tr>
<td >string1:</td>
<td>
<h:inputText style="width: 200px" value="#{AjaxTestBacking.string1}">
<a4j:support event="onkeyup" action="#{AjaxTestBacking.updateString1}" reRender="string1panel"/>
</h:inputText>
</td>
</tr>
<h:panelGroup id="string1panel" rendered="#{AjaxTestBacking.displayString1Xform}">
<tr>
<td>string1 reversed:</td>
<td>
<h:outputText style="width: 200px" value="#{AjaxTestBacking.string1Xform}" />
</td>
</tr>
</h:panelGroup>
<tr>
<td>string2:</td>
<td>
<h:inputText style="width: 200px" value="#{AjaxTestBacking.string2}">
<a4j:support event="onkeyup" action="#{AjaxTestBacking.updateString2}" reRender="string2panel"/>
</h:inputText>
</td>
</tr>
<h:panelGroup id="string2panel" rendered="#{AjaxTestBacking.displayString2Xform}">
<tr>
<td>string2 reversed:</td>
<td >
<h:outputText style="width: 200px" value="#{AjaxTestBacking.string2Xform}" />
</td>
</tr>
</h:panelGroup>
</table>
</h:form>
</h:panelGroup>
</body>
</html>
and the backing bean:
import java.io.Serializable;
@SuppressWarnings("serial")
public class AjaxTestManager extends AbstractManager implements Serializable {
private String string1;
private String string2;
private String string1Xform;
private String string2Xform;
private Boolean displayString1Xform;
private Boolean displayString2Xform;
public AjaxTestManager() {
string1 = "test string 1";
string2 = "test string 2";
updateString1();
updateString2();
}
public void updateString1() {
string1Xform = new StringBuilder(string1).reverse().toString();
displayString1Xform =string1Xform.length() > 5 ? true : false;
}
public void updateString2() {
string2Xform = new StringBuilder(string2).reverse().toString();
displayString2Xform = string2Xform.length() > 5 ? true : false;
}
public String getString1() {
return string1;
}
public void setString1(String string1) {
this.string1 = string1;
}
public String getString2() {
return string2;
}
public void setString2(String string2) {
this.string2 = string2;
}
public String getString1Xform() {
return string1Xform;
}
public void setString1Xform(String string1Xform) {
this.string1Xform = string1Xform;
}
public String getString2Xform() {
return string2Xform;
}
public void setString2Xform(String string2Xform) {
this.string2Xform = string2Xform;
}
public Boolean getDisplayString1Xform() {
return displayString1Xform;
}
public void setDisplayString1Xform(Boolean displayString1Xform) {
this.displayString1Xform = displayString1Xform;
}
public Boolean getDisplayString2Xform() {
return displayString2Xform;
}
public void setDisplayString2Xform(Boolean displayString2Xform) {
this.displayString2Xform = displayString2Xform;
}
}
I apologize if I'm fundamentally misunderstanding something about richfaces here - I'm somewhat of a noob to richfaces ajax, so please bear with me! I shared this code with my colleague who built the app and he is stumped as well. I've searched on google and SO and found a javascript-based answer, but I'm trying to understand how to do this with richfaces components. Other questions: Is the 'rendered' attribute the way to go here with dynamically showing/hiding parts of the page, or should I be using the 'visible' attribute? also, is the 'reRender' attribute on a4j:support supposed to be the jsf/'server-side' id of the element as I originally understood it, or the rendered client-side element ID as indicated here? Just trying to figure out if I'm misunderstanding something, limited by my jsf/richfaces version, or just generally going crazy :)