2011-09-07 49 views
2

我有一个要求,即使用jsf 2.0定制组件动态创建面板。面板中的控件将从xml动态读取并在相应对象的选择上呈现(例如:如果选择了Person,我应该渲染一个面板,该面板将具有与以下人员相关的控件:人员年龄字段(inputtext),人员DOB(日历)等)。有关JSF 2.0定制组件和Primefaces的帮助

我想从扩展UIComponentBase的组件类中呈现它。

ResponseWriter writer = Util.getResponseWriter(context); 
//start the <table> tag 
writer.startElement(Constants.STR_TABLE, this); 

//start the <tr> tag 
writer.startElement(Constants.STR_TR, this); 

//start the <td> tag 
writer.startElement(Constants.STR_TD, this); 

//encode the button 1 component inside this <td> 
encodeAllComponent(context, getMyPrimePanel()); 

// end the <td> tag 
writer.endElement(Constants.STR_TD); 

//end the <tr> tag 
writer.endElement(Constants.STR_TR); 


//end the <table> tag 
writer.endElement(Constants.STR_TABLE); 

    //private variable to render a panel 
    private Panel myPrimePanel; 

    /** 
    * @return the myPrimePanel 
    */ 
    public Panel getMyPrimePanel() { 
     System.out.println("inside the panel get method------"); 
     if (myPrimePanel.getChildCount() <= 1) { 
       System.out.println("inside the panel creation function"); 
       InputText input = new InputText(); 
       myPrimePanel.getChildren().add(input); 

     } 
     System.out.println("inside the panel get method-------------"); 
     return myPrimePanel; 
    } 

    /** 
    * @param myPrimePanel the myPrimePanel to set 
    */ 
    public void setMyPrimePanel(Panel myPrimePanel) { 
     System.out.println("inside the panel get method-------------"); 
     //initialize the button 1 component 
     this.myPrimePanel = myPrimePanel; 
    } 

我已经这样做了。但是我得到一个空指针异常。具有已定义控件的面板如何动态呈现?

这就是我得到 -

====将开始渲染==== 面板get方法里面------ 2011年9月7日上午10时01分42秒com.sun.faces.context.PartialViewContextImpl $ PhaseAwareVisitCallback访问 SEVERE:java.lang.NullPointerException

+2

检查异常的堆栈跟踪(在服务器日志中)。必须有NPE的行号,例如“在xy行的NullPointerException”。告诉我们它在代码中的哪一行。这会让我们更容易帮助你。 –

+0

感谢您的回复。但它没有显示任何行号。 – JaveDeveloper

回答

2

myPrimePanel为空。您需要为其指定一个实例,使其不为空。

但是,我认为你是以错误的方式去完成这项任务。您不应该在渲染阶段将组件添加到树中。据推测,你想要读取,验证和将数据输入到模型中一段时间​​。

encodeBegin中发射您的开始元素。在encodeEnd中发出您的最终元素。不要覆盖encodeChildren,并确保getRendersChildren返回false(这是默认值)。

在还原视图阶段使用绑定属性设置动态组件。使用类型UIComponent添加请求范围管理bean,并使用EL将其绑定到视图中的元素。在getter中,如果该属性为null,则创建自定义控件的新实例并添加任何children


考虑这样的观点:

<h:form> 
    <h:panelGroup id="myPanel" binding="#{componentMakerBean.panel}" /> 
    <h:commandButton value="go" action="#{componentMakerBean.dumpValuesAction}" /> 
</h:form> 

,创建面板和一个bean填充:

/** Request scope bean defined in faces-config.xml */ 
public class ComponentMakerBean { 
    private UIPanel panel; 

    public UIPanel getPanel() { 
    if(panel == null) { 
     panel = new HtmlPanelGroup(); 
     for(int i=0; i<3; i++) { 
     panel.getChildren().add(new HtmlInputText()); 
     } 
    } 
    return panel; 
    } 

    public void setPanel(UIPanel panel) { this.panel = panel; } 

    public String dumpValuesAction() { 
    for(Object kid : panel.getChildren()) { 
     if(kid instanceof ValueHolder) { 
     ValueHolder valueHolder = (ValueHolder) kid; 
     System.out.println(valueHolder.getValue()); 
     } 
    } 
    return null; //no navigation 
    } 
} 

在运行时,这将发射3个可编辑的文本字段,其值将被打印当按钮被点击时到日志。

此代码已经在使用Java 5的JSP中进行了测试& JSF 1.1。

+0

感谢您的回复。你能更清楚地告诉我如何创建?我对自定义组件非常陌生。我应该创建另一个扩展UIComponentTag类的类吗?在setProperties中,我应该使用EL来做valueBinding吗?你能给同样的片段吗? – JaveDeveloper

+0

@deepika - 您不需要使用我概述的方法添加任何附加标签;你只需要使用组件绑定功能。有关行为的详细信息,请参阅JSF规范。我已经添加了一些示例代码。 – McDowell

+0

雅这是正确的。但是这里不使用自定义组件。但我的要求是使用自定义组件。 :(我能够以你指定的方式呈现控件,但我应该使用自定义组件来做同样的事情,而且在jsf 2.0中,它不允许包含tld文件,因为它只允许facelets。(.xhtml)页面 – JaveDeveloper