我正在尝试根据Keith Strickland的例子为XPage构建一个JSF库控件。
我在构建FileDownloadControl时遇到了一些麻烦 这是我构建的代码:
public class Libcontrol extends UIComponentBase implements FacesComponent {
private static final String RENDERER_TYPE = "de.chris.Libcontrol ";
private static final String COMPONENT_FAMILY = "de.chris";
public Libcontrol() {
setRendererType(RENDERER_TYPE);
}
@Override
public String getFamily() {
return COMPONENT_FAMILY;
}
@SuppressWarnings("unchecked")
public void initBeforeContents(FacesContext arg0) throws FacesException {
FacesContext context;
ExpressionEvaluatorImpl evaluator;
context = FacesContext.getCurrentInstance();
evaluator = new ExpressionEvaluatorImpl(context);
XspFileDownload result = new XspFileDownload();
String sourceId = "fileDownload1/@value";
String valueExpr = "#{document1.FileField}";
ValueBinding value = evaluator.createValueBinding(result, valueExpr, sourceId,Object.class);
result.setValueBinding("value", value);
result.setDisplayLastModified(true);
result.setAllowDelete(true);
result.setTitle("filedown");
result.setRows(30);
result.setId("fileDownload1");
this.getChildren().add(result);
}
public void buildContents(FacesContext arg0, FacesComponentBuilder arg1) throws FacesException {
// Do Nothing
}
public void initAfterContents(FacesContext arg0) throws FacesException {
// Do nothing
}
}
有人知道为什么控件没有完全渲染? 当我查看HTML代码时,我看到控件中的starttag但没有要下载的文件 是的,我已将文件上传到相应的NotesDocument。
这是我分别复制的渲染器:
public class MainLibcontrolRenderer extends Renderer {
@Override
public void encodeBegin(FacesContext context, UIComponent component) {
try {
super.encodeBegin(context, component);
context = FacesContext.getCurrentInstance();
UIViewRootEx rootEx = (UIViewRootEx) context.getViewRoot();
/*rootEx.setDojoParseOnLoad(true);
rootEx.setDojoTheme(true);*/
ResponseWriter writer = context.getResponseWriter();
writer.startElement("fieldset", component);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void encodeChildren(FacesContext context, UIComponent component) {
try {
super.encodeChildren(context, component);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void encodeEnd(FacesContext context, UIComponent component) {
try {
super.encodeEnd(context, component);
ResponseWriter writer = context.getResponseWriter();
writer.endElement("fieldset");
} catch (Exception e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:0)
Stephan是对的:内容不呈现的原因是你没有构建它们。在实现FacesComponent时,buildContents方法通常应该指示FacesComponentBuilder启动构建过程; e.g:
arg1.buildAll(arg0, this, true);
注意:我正在使用您示例中的参数名称;理想情况下,您应该使用有意义的参数名称,如“context”和“builder”。
上面提到的buildAll方法使组件树正确反映了init方法期间对结构所做的任何更改。如果跳过此步骤,后续的JSF阶段(包括RENDER_RESPONSE)将不知道您注入的任何组件。
顺便说一句,Keith也提出了一个有用的观点:对值绑定和其他属性进行硬编码 - 至少在您提供的示例中 - 往往会破坏定义可重用控件的目的。我想回应Keith的建议,仔细研究一下你要完成的工作,以确定自定义组件是否真的是合适的实现。最后一个注意事项:在注入组件上以编程方式设置id属性时要特别小心......最终可能会出现在编译期间无法检测到的名称冲突。换句话说,Designer无法警告你......它只会在运行时断开,失败的原因可能并不明显。