我在facelets中遇到自定义组件的问题。第一次呈现页面时,在组件类上正确设置属性。但是,提交表单时,不会设置属性。
这是我用来测试它的类。
public class TestEcho extends UIData
{
/** Logger. */
private static Log log = LogFactory.getLog(TestEcho.class);
private String msg;
public TestEcho()
{
log.debug("Constructor.");
}
public void encodeEnd(FacesContext context) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
writer.startElement("div", this);
writer.writeText("The value of msg is '" + msg + "'.", null);
writer.endElement("div");
}
public void setMsg(String msg)
{
log.debug("Setting msg to '" + msg + "'.");
this.msg = msg;
}
}
该组件在.xhtml页面中使用。
<h:form>
<v:testEcho msg="hello" />
<h:commandButton action="#{PictureManager.trigger}" value="Click" />
</h:form>
当页面首次呈现时,组件会呈现以下html代码。
<div>The value of msg is 'hello'.</div>
单击该按钮时,会显示此按钮。
<div>The value of msg is 'null'.</div>
从日志中,您可以看到组件再次构建,但未设置该属性。
13:23:42,955 DEBUG [TestEcho] Constructor.
13:23:42,955 DEBUG [TestEcho] Setting msg to 'hello'.
----- Button was pressed here -----
13:25:48,988 DEBUG [TestEcho] Constructor.
13:25:49,144 DEBUG [PictureManager] Button pressed.
根据我的理解,facelets将所有属性连接到组件,因此我不需要标记类,但我不明白为什么第一次正确设置属性,而不是第二次。
答案 0 :(得分:1)
您必须通过覆盖saveState和restoreState方法来保存您的州。
因此, saveState 必须返回一个Serializable对象(例如JavaBean或Object []数组),其中包含 msg 中的值以及<返回的任何内容EM> super.saveState 。此对象将提供给 restoreState ,其中方法必须从对象恢复 msg 并将父状态传递给 super.restoreState 。
答案 1 :(得分:1)
麦克道尔的答案就是这么做的。为了完整起见,这是我添加的两种方法。
public Object saveState(FacesContext context)
{
Object[] rtrn = new Object[2];
rtrn[0] = super.saveState(context);
rtrn[1] = msg;
return rtrn;
}
public void restoreState(FacesContext context, Object state)
{
Object[] values = (Object[]) state;
super.restoreState(context, values[0]);
msg = (String) values[1];
}