0

我正在尝试根据 Keith Strickland 的示例为 XPages 构建 JSF 库控件。

http://xprentice.gbs.com/A55BAC/keithstric.nsf/default.xsp?documentId=82770C11FA7B9B21852579C100581766

我在构建 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();
    }
}

}

4

1 回答 1

0

Stephan 是对的:内容不呈现的原因是您没有构建它们。在实现 FacesComponent 时,buildContents 方法通常应该指示 FacesComponentBuilder 启动构建过程;例如:

arg1.buildAll(arg0, this, true);

注意:我使用的是您示例中的参数名称;理想情况下,您应该使用有意义的参数名称,例如“context”和“builder”。

上面提到的 buildAll 方法使组件树正确地反映在 init 方法期间对结构所做的任何更改。如果您跳过此步骤,后续的 JSF 阶段(包括 RENDER_RESPONSE)将不知道您注入的任何组件。

顺便说一句,Keith 也提出了一个有效的观点:硬编码值绑定和其他属性 - 至少在您提供的示例中 - 往往会破坏定义可重用控件的目的。我会回应 Keith 的建议,仔细研究您要完成的工作,以确定自定义组件是否真的是合适的实现。最后一个警告:以编程方式在注入的组件上设置 id 属性时要格外小心……您最终可能会遇到在编译期间无法检测到的名称冲突。换句话说,Designer 无法警告您……它只会在运行时中断,而失败的原因可能并不明显。

于 2012-07-18T05:12:44.930 回答