Search code examples
jsftabsrichfacestabpanel

RichFaces dynamic TabPanel


How to implement a simple add/remove dynamic <rich:tabPanel>?

(I've seen people asking this around so I thought postin a Q&A of a simple implementation)


Solution

  • The implementation has 3 custom classes:

    1. Content: contains the values to be displayed in a tab;
    2. ItemTab: contais an UITab object and a Content object;
    3. MyTabs: EJB managed bean that provides access to the tabs and adding/removal methods.

    The code is:

    Content:

    public class Content {
    
        String name;
        String job;
        String dept;
    
        public Content() {
            name = "John Doe";
            job = "None";
            dept = "None";
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getJob() {
            return job;
        }
    
        public void setJob(String job) {
            this.job = job;
        }
    
        public String getDept() {
            return dept;
        }
    
        public void setDept(String dept) {
            this.dept = dept;
        }
    }
    

    TabItem:

    public class TabItem {
    
        UITab component;
        Content content;
    
        public TabItem() {
            component = new UITab();
            content = new Content();
        }
    
        public UITab getComponent() {
            return component;
        }
    
        public void setComponent(UITab tab) {
            this.component = tab;
        }
    
        public Content getContent() {
            return content;
        }
    
        public void setContent(Content content) {
            this.content = content;
        }
    }
    

    MyTabs:

    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    import javax.annotation.PostConstruct;
    import javax.enterprise.context.SessionScoped;
    import javax.inject.Named;
    
    @Named
    @SessionScoped
    public class MyTabs implements Serializable {
    
        private List<TabItem> tabs;
    
        public MyTabs() {
            tabs = new ArrayList<TabItem>();
        }
    
        @PostConstruct
        private void init() {
            createTab();
            createTab();
            createTab();
        }
    
        public void createTab() {
            TabItem tab = new TabItem();
    
            tab.getComponent().setId("Tab" + (tabs.size()+1));
            tab.getComponent().setHeader("Tab " + (tabs.size()+1));
            tab.getContent().setName("John Doe " + (tabs.size()+1));
            tab.getContent().setJob("Salesman " + (tabs.size()+1));
            tab.getContent().setDept("Sales " + (tabs.size()+1));
    
            tabs.add(tab);
        }
    
        public void removeTab(TabItem tab) {
            tabs.remove(tab);
        }
    
        public List<TabItem> getTabs() {
            return tabs;
        }
    
        public void setTabs(List<TabItem> tabs) {
            this.tabs = tabs;
        }
    }
    

    tabview.xhtml:

    <h:commandLink value="Add Tab" 
                       actionListener="#{myTabs.createTab()}"/>
    <rich:tabPanel switchType="client">
        <c:forEach items="#{myTabs.tabs}" var="tab">
            <rich:tab value="#{tab.component}">
                <f:facet name="header">
                    <h:outputLabel value="#{tab.component.header}"/>
                    <h:commandLink value="  X" actionListener="#{myTabs.removeTab(tab)}"/>
                </f:facet>
    
                <h:panelGrid columns="2">
                    <h:outputLabel value="Name: "/>
                    <h:outputLabel value="#{tab.content.name}"/>
                    <h:outputLabel value="Dept: "/>
                    <h:outputLabel value="#{tab.content.dept}"/>
                    <h:outputLabel value="Job: "/>
                    <h:outputLabel value="#{tab.content.job}"/>
                </h:panelGrid>
            </rich:tab>
        </c:forEach>            
    </rich:tabPanel>