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:




RichFaces



   
     
       
       
          
	      
       
       
      
   



Managed bean:

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<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 responses to “Dynamically creating RichFaces tabs”

  1. 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. Looks like it’s a class loader issue. You might have two different RichFaces versions loaded by different class loaders.

  3. 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?

  4. Check and make sure there is no other version of RichFaces somewhere in the classpath.

  5. Resolved. Thank you!

  6. 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.

  7. 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.

  8. Thanks for the reply.

    Is there any other option I might use?

    Thanks,
    Yaniv.

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

    ...
    
    ...
    

    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.

  10. 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.

  11. a4j:include will not be processed if you include it dynamically and I haven’t tried ui:include.

  12. UIinclude doesn’t work

  13. Please reply to this max

  14. i have the same problem i want to create include dynamically to include a page in rich tab

  15. It’s not possible to create a4j:include dynamically. I haven’t tried ui:include.

  16. 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

  17. I can’t see your code. Paste the code into http://tinypaste.com

  18. 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.

  19. @fm: Add:

    tab.setName(i);

    See bean line number 39.

  20. 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?

  21. @sachin: what is encodeBegin method?

  22. 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 { }

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

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

  25. 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.

  26. @hari: such functionality is not built-in. You would have to extend the component to add such functionality.

  27. 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

  28. Its working. Your the man

  29. 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

    1. I’m not sure to be honest with you, it’s been some time since I tried this example.

Leave a comment