4

I am working on a project using Primefaces 3.5 & JSF2.1 (Mojarra)

I have created a primefaces <p:tabView id="tabsVw" dynamic="false"> with two tabs inside and each tab has a primefaces datatable

 <h:form> 
        <p:tabView  dynamic="false">
        <p:ajax event="tabChange" listener="#{tstTab.onDtlTabChanged}" />

            <p:tab title="tab1">
                <p:dataTable value="#{tstTab.list1}" var="v1">
                    <p:column>
                        <h:outputText value="#{v1}"/>
                    </p:column>
                </p:dataTable>
            </p:tab>

            <p:tab title="tab2">
                <p:dataTable value="#{tstTab.list2}" var="v2">
                    <p:column>
                        <h:outputText value="#{v2}"/>
                    </p:column>
                </p:dataTable>          
            </p:tab>
        </p:tabView>
    </h:form>

and inside the bean (view scoped)

@ManagedBean
@ViewScoped
public class TstTab {

    private List<String> list1;
    private List<String> list2;

    public TstTab(){
        list1 = new ArrayList<String>();
        list2 = new ArrayList<String>();


        list1.add("List 1 - Str 1");
        list1.add("List 1 - Str 2");
        list1.add("List 1 - Str 3");
        list1.add("List 1 - Str 4");
        list1.add("List 1 - Str 5");

        list2.add("List 2 - Str 1");
        list2.add("List 2 - Str 2");
        list2.add("List 2 - Str 3");
        list2.add("List 2 - Str 4");
        list2.add("List 2 - Str 5");            
    }


    public void onDtlTabChanged(TabChangeEvent event) {
        System.out.println("000000000000000000");
    }


    public List<String> getList1() {
        System.out.println("11111111111111");
        return list1;
    }


    public List<String> getList2() {
        System.out.println("222222222222222222");
        return list2;
    }

}

now the problem is when run the application and try to navigate (change) between tabs, but I can see that the onDtlTabChanged is called after calling getters, so that is a big problem.

and if change the tabView from static to dynamic, then the behavior is random, in other words the calling to the change event is happening somewhere in the middle of getters.

Thank you in advance.

Community
  • 1
  • 1
Ali Saleh
  • 258
  • 1
  • 4
  • 12
  • You set dynamic="true", so why did you update tab 1 in ajax ? – Rong Nguyen Apr 10 '13 at 16:38
  • I have cache="false", so if the user navigate to the second tab and then goes to the first one, I have to re-fetch the data again – Ali Saleh Apr 11 '13 at 06:01
  • So if the user navigate to the second tab and then goes to the third tab ? – Rong Nguyen Apr 11 '13 at 06:08
  • I did not understand your point, the idea is that there are three tabs each one with a datatable and I need to refresh the data each time a user click a tab, but Primefaces is loading tab content before finishing the changeTab ajax event – Ali Saleh Apr 11 '13 at 06:29
  • I tested with Primefaces 3.5 and jsf(morjarra 2.1.20), it work fine, so you should test with simple example first and reference to above code, good luck ! – Rong Nguyen Apr 11 '13 at 07:13
  • Tnanks, but I have tested it using a very simple example but its the same ( I have updated the post above with the new example) to make it more specific. – Ali Saleh Apr 11 '13 at 08:36

3 Answers3

4

Well I think that its a primefaces BUG, I found a workaround which as the following

  1. Do not use a global form (form for the tabView itself) instead use a form for each tab (inside it that surround the datatable)

  2. You have to add a dummy tab to be the first one that must include a form which some static data or pre-loaded data inside

Thats all,

the problem was that the ajax request is inside the global form and it cause the datatables to get their data first before ajax request, the strange thing with Primefaces that if you do not add the first dummy tab it will always execute the first form inside the tabs and get its data and this will cause a problem

regards ,

Ali Saleh
  • 258
  • 1
  • 4
  • 12
2

I think the answer of ali saleh is right.

If you get problems with the tabchangelistener perhaps this can help you:

I had a similar problem with Primefaces 5.1

As long as i put the tabview into a form everything worked fine. But because i wanted to use seperate forms in my tabs i had to remove the surrounding form of the tabview to avoid nested forms. Without the surrounding form the ajax event didn´t get triggered any more when changing the tab.

My solution was to use a remotecommand in a form parallel to the tabview.
The remotecommand is triggered by the onTabChange attribute of the tabview element. At that call i forwarded the index parameter to the global request parameters.

<p:tabView id="rootTabMenu" styleClass="tabcontainer" prependId="false" 
        activeIndex="#{sessionData.activeTabIndex}" widgetVar="rootTabMenu"
        onTabChange="tabChangeHelper([{name: 'activeIndex', value: index}])">
    // Tabs...  
</p:tabView>

<h:form id="tabChangeHelperForm">
    <p:remoteCommand name="tabChangeHelper" actionListener="#{sessionData.onTabChange()}" />
</h:form>    

In the backing bean i catched the value again from the request parameter map and set the active index.

public void onTabChange()
{   
    FacesContext context = FacesContext.getCurrentInstance();
    Map<String, String> paramMap = context.getExternalContext().getRequestParameterMap();
    String paramIndex = paramMap.get("activeIndex");
    setActiveTabIndex(Integer.valueOf(paramIndex));
    System.out.println("Active index changed to " + activeTabIndex);
}    

Hope that can help you

maimArt
  • 389
  • 1
  • 11
  • Please don't just link to an answer. It's allowed to show the solution here **and** link to the answer. That way the asker still knows what to do when the url is no longer valid. – Benjamin Diele Nov 14 '14 at 10:25
1

It work fine in Primefaces 3.5 and mojarra 2.1.20, my code: bean:

@ManagedBean(name = "tabview")
@ViewScoped    
public class TabView implements Serializable {

        private static final long serialVersionUID = 1L;
        private List<Car> l1;
        private List<Car> l2;
        private List<Car> l3;

        public TabView() {
            l1 = new ArrayList<Car>();
            l2 = new ArrayList<Car>();
            l3 = new ArrayList<Car>();

            Car c1 = new Car("c1", "a1");
            Car c2 = new Car("c21", "a21");
            Car c3 = new Car("c31", "a31");
            Car c4 = new Car("c41", "a41");
            Car c5 = new Car("c51", "a51");
            Car c6 = new Car("c61", "a61");
            Car c7 = new Car("c71", "a71");
            Car c8 = new Car("c81", "a81");
            Car c9 = new Car("c91", "a91");
            l1.add(c1);
            l1.add(c2);
            l1.add(c3);

            l2.add(c4);
            l2.add(c5);
            l2.add(c6);

            l3.add(c7);
            l3.add(c8);
            l3.add(c9);
        }

        public void hand(TabChangeEvent event) {
            Car c1 = new Car("c1", "a1");
            Car c2 = new Car("c1", "a1");
            Car c3 = new Car("c1", "a1");
            Car c4 = new Car("c1", "a1");
            Car c5 = new Car("c1", "a1");
            Car c6 = new Car("c1", "a1");
            Car c7 = new Car("c1", "a1");
            Car c8 = new Car("c1", "a1");
            Car c9 = new Car("c1", "a1");
            l1.add(c1);
            l1.add(c2);
            l1.add(c3);

            l2.add(c4);
            l2.add(c5);
            l2.add(c6);

            l3.add(c7);
            l3.add(c8);
            l3.add(c9);
        }

        public List<Car> getL1() {
            return l1;
        }

        public void setL1(List<Car> l1) {
            this.l1 = l1;
        }

        public List<Car> getL2() {
            return l2;
        }

        public void setL2(List<Car> l2) {
            this.l2 = l2;
        }

        public List<Car> getL3() {
            return l3;
        }

        public void setL3(List<Car> l3) {
            this.l3 = l3;
        }
    }

xhtml:

  <p:tabView id="mtrlDtlTabs" dynamic="true" cache="false">  
                    <p:ajax event="tabChange" update="t1 t2 t3" listener="#{tabview.hand}"/>
                    <p:tab id="t1" title="1">
                        <p:dataTable id="l1" value="#{tabview.l1}" var="l1">
                            <p:column headerText="l1">#{l1.manufacturer}</p:column>
                            <p:column headerText="l2">#{l1.model}</p:column>
                        </p:dataTable>
                    </p:tab>
                    <p:tab id="t2" title="2">
                        <p:dataTable id="l2" value="#{tabview.l2}" var="l2">
                            <p:column headerText="l2">#{l2.manufacturer}</p:column>
                            <p:column headerText="l22">#{l2.model}</p:column>
                        </p:dataTable>
                    </p:tab>
                    <p:tab id="t3" title="3">
                        <p:dataTable id="l3" value="#{tabview.l3}" var="l3">
                            <p:column headerText="l3">#{l3.manufacturer}</p:column>
                            <p:column headerText="l33">#{l3.model}</p:column>
                        </p:dataTable>
                    </p:tab>
                </p:tabView>
Rong Nguyen
  • 4,143
  • 5
  • 27
  • 53
  • Try to add a print statement in the getters and you will see that there is a strange sequence in calling them – Ali Saleh Apr 14 '13 at 05:59