Dynamically creating RichFaces tabs

I saw a reference (http://mkblog.exadel.com/?p=115) to my blog on one of the Brazilian JSF forums. I translated the thread using Google and it looked like someone was asking how to create RichFaces tabs dynamically. So, here is quick example.

XHTML page:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:rich="http://richfaces.org/rich"
	xmlns:a4j="http://richfaces.org/a4j">
<head>
<title>RichFaces</title>
</head>
<body>
<h:form>
   <rich:panel>
     <h:panelGrid columns="1">
       <h:outputText value="How many tabs would you like?" />
       <h:panelGroup>
          <h:inputText value="#{tabsBean.numOfTabs}" size="2" />
	      <a4j:commandButton value="Create"
                   actionListener="#{tabsBean.createTabs}" reRender="tabs" />
       </h:panelGroup>
       </h:panelGrid>
      <h:panelGrid id="tabs" binding="#{tabsBean.panelGrid}"/>
   </rich:panel>
</h:form>
</body>
</html>

Managed bean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package tabs;
 
import javax.faces.application.Application;
import javax.faces.component.html.HtmlPanelGrid;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
 
import org.richfaces.component.html.HtmlTab;
import org.richfaces.component.html.HtmlTabPanel;
 
public class TabsBean {
 
   private HtmlPanelGrid panelGrid;
   private Integer numOfTabs;
 
   public Integer getNumOfTabs() {
	return numOfTabs;
   }
   public void setNumOfTabs(Integer numOfTabs) {
	this.numOfTabs = numOfTabs;
   }
   public TabsBean() {
   }
   public HtmlPanelGrid getPanelGrid() {
	return panelGrid;
   }
   public void setPanelGrid(HtmlPanelGrid panelGrid) {
	this.panelGrid = panelGrid;
   }
   public void createTabs (ActionEvent event){		
	FacesContext context = FacesContext.getCurrentInstance();
	Application application = context.getApplication();
	HtmlTabPanel tabPanel = (HtmlTabPanel)application.createComponent(HtmlTabPanel.COMPONENT_TYPE);
	tabPanel.setSwitchType("ajax");
 
	for (int i=0; i&lt;numOfTabs; i++){
		HtmlTab tab = (HtmlTab)application.createComponent(HtmlTab.COMPONENT_TYPE);
		tab.setLabel("Nice Tab # "+(i+1));
		tab.setName(i);
                tabPanel.getChildren().add(tab);
	}
 
	panelGrid.getChildren().clear();
	panelGrid.getChildren().add(tabPanel);
   }
}

You will get this:

tabs1.png

tabs2.png

30 comments

  1. lijian

    hey max

    I created a project to test this example, but have some errors. And my environment: eclipse 3.3.x; ant1.7.0; jboss4.2.3GA and jboss-seam-2.1.0. I think the errors should be the environment or config issues. Can you tell me your detail config? thank you a lot.

    Stack Trace:
    Exception during request processing:
    Caused by javax.servlet.ServletException with message: “/layout/func-template.xhtml @44,64 actionListener=”#{tabsBean.createTabs}”: java.lang.ClassCastException: org.richfaces.component.html.HtmlTabPanel cannot be cast to org.richfaces.component.html.HtmlTabPanel”
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:277)
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
    org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:38)
    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:150)
    org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
    org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:379)
    org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:506)
    org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:44)
    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
    org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
    org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
    java.lang.Thread.run(Unknown Source)

  2. lijian

    Thanks for your answer, and I have replaced all richfaces jars with the richfaces3.2.2.SR1, but the error still exists. Do I need to modify any config files?

  3. yandav

    Hello Max,

    I’m trying to add dynamic content to each new tab by using an include.
    however I’m not successful.

    here is what I do:

    Include includeTag = new Include();

    includeTag.setId(“inc” this.count );
    includeTag.setViewId(“snippet.xhtml”);

    tab.setId(“newtab” this.count );
    tab.getChildren().add(includeTag);

    tabPanel.getChildren().add(tab);
    tabPanel.setSelectedTab(“newtab” this.count );

    the tab is being added but no content inside.

    Please help,
    Thank you very much,
    Yaniv.

  4. max

    It’s not possible to add a4j:include dynamically right now. The component is added to the tree but the subtree (that actual include) is not processed.

  5. max

    One option is to do this, although, you will need to know how many tabs you have ahead of time:

    ...
    <a4j:include viewId="#{bean.fileName}"/>
    ...

    Another option is to try using ui:include instead of a4j:include with includeFacelet(..) method:

    public void apply(FaceletContext ctx, UIComponent parent)
       throws IOException, FacesException, FaceletException, ELException {
       String path = this.src.getValue(ctx);
       VariableMapper orig = ctx.getVariableMapper();
       ctx.setVariableMapper(new VariableMapperWrapper(orig));
       try {
          this.nextHandler.apply(ctx, null);
          ctx.includeFacelet(parent, path);
        } finally {
           ctx.setVariableMapper(orig);
        }
    }

    I haven’t tried, if you try it, let me know if it works.

  6. yandav

    Hello again Max,

    I tried to follow up on your suggestion but I’m really not an expert.

    From what I have understood, I tried writing a tag handler and adding that to the tab. however the tab wont accept taghandlers only UIcomponents.

    Is there a way to make the include processed?

    I would really appreciate your help on this issue.
    A full code example would be even more appreciated :)

    Thank you very much in advance,
    Yaniv.

  7. santhosh

    Insert title here

    I am new to fiji charts… but i am using jsf richfaces…
    pls help i am gettting error like this..
    java.lang.ClassCastException: org.ajax4jsf.component.AjaxViewRoot cannot be cast to com.exadel.fiji.component.html.HtmlBarChart

  8. fm

    Hi
    I tried your example but getting an error.

    Strack Trace:
    java.lang.NullPointerException
    at org.richfaces.renderkit.TabPanelRendererBase.encodeTabs(TabPanelRendererBase.java:354)
    at org.richfaces.renderkit.html.TabPanelRenderer.doEncodeBegin(TabPanelRenderer.java:248)
    at org.richfaces.renderkit.html.TabPanelRenderer.doEncodeBegin(TabPanelRenderer.java:200)
    at org.ajax4jsf.renderkit.RendererBase.encodeBegin(RendererBase.java:101)
    at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:788)
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:269)
    at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:117)
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:812)
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:271)
    at com.sun.faces.renderkit.html_basic.GridRenderer.encodeChildren(GridRenderer.java:242)
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:812)
    at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:282)
    at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:124)
    at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:67)
    at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:115)
    at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:67)
    at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:115)
    at org.ajax4jsf.renderkit.AjaxContainerRenderer.encodeAjax(AjaxContainerRenderer.java:123)
    at org.ajax4jsf.component.AjaxViewRoot.encodeAjax(AjaxViewRoot.java:677)
    at org.ajax4jsf.component.AjaxViewRoot.encodeChildren(AjaxViewRoot.java:548)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:886)
    at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:592)
    at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100)
    at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:106)
    at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:144)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:245)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178)
    at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
    at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:390)
    at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:517)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:619)

    Your help greatly appreciated. Thank you.

  9. sachin

    Sorry. I want to use the intialisation of tabs in encodeBegin method, can we do that??i tried putting the code of cretaeTabs methos in encodeBegin method but it doesnt work.can we initialise the richfaces tabs
    in the start up?

  10. sachin

    max, the encodeBegin method of the Renderer Class where we have the ResponseWriter to generate the code.We already have a tabed system using a pure html one but want to use richfaces tabs in this method.

    public void encodeBegin(FacesContext context, UIComponent component) throws IOException { }

  11. max

    @sachin: check JSF specification about this, but in general it should be possible to crate tab/tabPanel inside encodeBegin(…).

  12. sachin

    MAX, I have tried several ways but couldnt.looks like encodeBegin allows only pure html based components to be rendered.

  13. hari

    Hi Max,

    I have a requirement like need to display more tabs in a single page, since there are more, I kept horizontal scroll bar, but I do not want it. I want an arrow indicating more tabs ahead like how firefox,chrome or IE tabbed browsers behave.

    How can achieve this for rich tabs.

  14. rom2pac

    hi,
    i Create tabpanel dynamically with the class “org.richfaces.component.html.HtmlTabPanel”
    i add for my tabpanel liste of tab it work well
    but my problem i want to add for each tab a datatable !!:(
    i obtain the message in my browser ” org.richfaces.component.html.HtmlTabPanel cannot be cast to org.richfaces.component.html.HtmlDataTable”
    how i can add datattable for ech tab

  15. kolossus

    Is there an alternative to this solution you’ve presented here? I’m asking this because of the current ViewScoped bug in mojarra where a viewscoped bean behaves like a request scoped bean when any component is bound to it. Primefaces offers dynamic component generation out of the box but i’m more comfortable with richfaces. Is there any way aroud this? Thx

Leave a Reply