I have a tab view with three tabs. The tab view seems to work correctly in the first two tab changes, but on the third I get a null-pointer as in
java.lang.NullPointerException
at org.primefaces.component.tabview.TabViewRenderer.encodeEnd(TabViewRenderer.java:59)
Also, TabChangeEvents have null data at this point.
Making the contents of the tabs minimal (just a line of text), I can see that the contents of the tabs are being appended onto each other. Once this happens, the issues begin.
Looking at the PrimeFaces source code, it seems that it's when trying to work with the tabToLoad
variable that is retrieved with the generated tabClientId
. I'm not certain that it should be in the branch of logic that deals with new tabs either.
My tab view looks as follows:
<p:tabView styleClass="entities-tabview" id="tabs" dynamic="true">
<p:ajax event="tabChange" listener="#{action.onTabChange}"
update="first-tab,second-tab"/>
<p:tab title="First Tab" id="first-tab">
tab one content
</p:tab>
<p:tab title="Second Tab" id="second-tab">
tab two content
</p:tab>
<p:tab title="Other Tab" id="other-tab">
// tab content
</p:tab>
</p:tabView>
It seems that the code checks if the var
parameter is set on the TabView. As we do not use one, it is null, so it goes into the new tab branch. The tab index is set on the tabview though. Any ideas about what could be wrong?
After some more investigation, I see that on a tab change the tab that should be changed to is specified via the request parameter with the client ID with _newTab
appended to it. The first two times this is set correctly, but on changing back to the tab it is not set, hence not being able to find the tab and the subsequent NPEs.
Updated Cause With the tabs being dynamic, and the ajax event firing, the tabs are changed and subsequently the ajax updates the tabs. This seems to cause the issue where both tabs are loaded into the same tab, which most likely is messing up the parameters later on.
But how to be able to do the tab change functions and have its details display in the tab?
The issue here is that you have the ajax updating both of the tabs. It seems that when it does this, the state of the tabs gets confused and you end up with the content of both tabs in one.
You can get around it by inserting the content into an h:panelGroup
and updating the panelgroup
instead of the tab
example below
<p:tabView styleClass="entities-tabview" id="tabs" dynamic="true">
<p:ajax event="tabChange" listener="#{action.onTabChange}"
update="one-content,two-content,other-content"/>
<p:tab title="First Tab" id="first-tab">
<h:panelGroup display="block" id="one-content">
tab one content
</h:panelGroup>
</p:tab>
<p:tab title="Second Tab" id="second-tab">
<h:panelGroup display="block" id="two-content">
tab two content
</h:panelGroup>
</p:tab>
<p:tab title="Other Tab" id="other-tab">
<h:panelGroup display="block" id="other-content">
// tab content
</h:panelGroup>
</p:tab>
</p:tabView>