我试过简单:
public class UIDemoComponent extends UIComponentBase {
private String someVariable; // this gets always cleared, getters/setters omitted
public UIDemoComponent() {
super(); // place breakpoint here
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
HtmlForm form = new HtmlForm();
form.setStyle("padding: 10px; background-color: blue;");
getChildren().add(form);
AjaxBehavior behavior = new AjaxBehavior();
behavior.setRender(Arrays.asList("@form"));
form.addClientBehavior("click", behavior);
}
}
我已经注册了一个标签处理程序并成功将组件插入到页面中。但是,当我单击渲染的蓝色表单时,JSF重新创建组件(捕获构造函数中的断点)。这样做的结果是任何实例变量都会丢失。如果总是重新创建数据,应该如何将数据保存到组件中?
我尝试覆盖并检查StateHolder
和PartialStateHolder
的状态存储机制,但运气不错:
@Override
public Object saveState(FacesContext context) {
return super.saveState(context); // breakpoint
}
@Override
public void restoreState(FacesContext context, Object state) {
super.restoreState(context, state); // breakpoint
}
当创建页面和组件时,JSF正在执行saveState
,但永远不会调用restoreState
。实际上,当处理AJAX请求时,会创建一个新的UIDemoComponent实例,但saveState
方法再次被称为,而不是restoreState
。
如何创建这样一个状态保存组件(通过AJAX请求保留实例字段)?
答案 0 :(得分:3)
似乎JSF正在对state
对象运行一些预检查,如果没有输入自定义字段,则根本不执行restoreState
。只有在将自定义值实际插入状态对象后,才会调用restoreState
。
例如:
@Override
public Object saveState(FacesContext context) {
Object[] rtrn = new Object[2];
rtrn[0] = super.saveState(context);
rtrn[1] = "dummy";
return rtrn;
}
在此之后,调用restoreState
并根据需要恢复属性字段。