p:tabView tabIndex access - jsf-2

I have a code like below.
<p:tabView value="#{bean.entityList}" id="tabView" var="item">
<p:tab title="#{item.name}">
.
.
.
</p:tab>
</p:tabView>
I want to access the index of the tab just like datatable's rowIndexVar. How can I get the tab index?

There is a very horrible workaround for this, which I don't recommend but it's the best I could come up with. It involves having a bit of Javascript to keep track of the tab count, and within each tab using more Javascript to generate the HTML that needs the tab index.
In the <head>of your page, initialise the tab counter;
<head>
<script>
// Global tab counter
tabCount = -1;
</script>
</head>
Then when you draw each tab, increment the counter. Within the tab, whenever you need the tab index, make a small script to generate the HTML with the index. For example:
<p:tabView value="#{bean.entityList}" id="tabView" var="item">
<p:tab title="#{item.name}">
<script>
// Increment the tab counter
tabCount++;
</script>
<!-- Now the tab content -->
The index of this tab is:
<script>
document.write(tabCount);
</script>
</p:tab>
</p:tabView>
As I said, it's horrible and makes me wince whenever I see it, but it works.

Related

Stop TabChange in primefaces <p:tabView>`

I am using Primefaces 5 and use which has severl tabs.
In each tab I have a dataTable which either can be in editable or not depending to user action.
I want to stay in the same tab and prevent tab change if user is editing a row, otherwise go to the clicked tab. How should i do it ??
This is my xhtml :
<p:tabView id="customerTab"
orientation="left"
dynamic="false"
cache="false"
widgetVar="detailsTab"
activeIndex="#{myBean.activTab}"
>
<p:ajax event="tabChange" listener="#{myBean.onTabChange}" update="customerTabv" />
<p:tab tab1> </p:tab>
<p:tab tab2> </p:tab>
This is my backing bean:
public void onTabChange(
TabChangeEvent event) {
if (Tab.isInEditMode()) {
FacesMessage msg = new FacesMessage("Tab Changed", "Active Tab: " + event.getTab().getId()
+ "You can not change the tab when you are in Edit mode!");
FacesContext.getCurrentInstance().addMessage(null, msg);
this.messagesTab.setActiveIndex(0);
// // RequestContext.getCurrentInstance().execute("tabWidget.select(0)");
activTab = 0;
FacesContext.getCurrentInstance().setProcessingEvents(false);
} else {
TabView tabView = (TabView) event.getComponent();
int activeIndex = tabView.getChildren().indexOf(event.getTab());
this.messagesTab.setActiveIndex(activeIndex);
activTab = activeIndex;
}
}
The solution in short boils down to this:
In the onstart of the rowEditInit ajax event, set a client-side variable that you are in edit mode
In the oncomplete of the rowEditCancel event, set the client-side variable that your are in a non-edit mode
In the oncomplete of the rowEdit event, set the client-side variable that your are in a non-edit mode
In the onstart of the tab change event, write some javascript that checks for the value of this edit variable and if in edit mode, return false. The tabChange should not happen then. If in non-edit mode, return true and the tabChange happens
Sorry, I do not write an answer for you with a fully working example. This is mainly because I do not want to/have the time to write it (never used inline editing myself for complexity reasons like this) AND think that people 'learn' more from hints then fully worked out code.
I had a lot of problems with tabView and nested dynamic elements like dataTable in it. So I use the tabView now only as trigger. This means the tabView has tabs but inside the tabs are not elements. I react with ajax listener to tab changes and update a specific area in my UI which shows the content that should be inside the tab.
For your problem this could be a solution. You can ignore the tab change event when the dataTable is edited.
Or disable the other tabs with tab disabled attribute.
My solution was some javascript. In order to stop tabchange:
<p:tabView id="tabView" activeIndex="#{controller.tabSelected}" onTabChange="handleTabChange(index);return false;"
Check primefaces_user_guide_6_2 for the handleTabChange function.
I also needed p:remoteCommand to send the new selected tab to the bean.

Primefaces TabView throwing a null-pointer on third load of tab

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>

JSF selectOneRadio, rendering only certain items

Is there any possibility rendering just certain items (based on their value) of radio buttons in jsf
e.g this below: (but this approach doesn't work)
<h:selectOneRadio value="#{user.favColor3}">
<f:selectItems rendered="c.colorValue eq 'red'" .... var="c"
</h:selectOneRadio>
So, I want to iterate over the items, and showing only the red item.
Thanks in advance.
Cs

Target specific tabs of a p:tabView in p:printer

I am trying to print multiple tabs but want to exclude some.
I tried the following:
<p:printer target="tabs:tab0,tabs:tab2" />
and
<p:printer target="tabs:tab0" />
<p:printer target="tabs:tab2" />
Neither worked.
I played somewhat around it and it works only for a specific tab if the tab is visible. You can thus definitely not specify multiple tabs. You might want to post an issue report about that to PrimeFaces, although solving that would be relatively hard.
As of now, to get it to work for a specific tab, you'd need to toggle the desired tab visible in the button's onclick handler before print action is performed. You can use the select() function of the <p:tabView> widget for this wherein you pass the zero-based tab index.
Here's a kickoff example.
<h:form id="form">
<p:tabView id="tabs" widgetVar="tabs">
<p:tab id="tab1" title="tab1">tab1</p:tab>
<p:tab id="tab2" title="tab2">tab2</p:tab>
<p:tab id="tab3" title="tab3">tab3</p:tab>
</p:tabView>
<p:commandButton type="button" icon="ui-icon-print" value="Print tab2" onclick="tabs.select(1)">
<p:printer target="tabs:tab2" />
</p:commandButton>
</h:form>

Update component from iframe

There are a <p:inputText> and a <p:commandButton>. I want to click the button to open a dialog with a table. When I select one row and press OK, I would like set the value of the selected row in the <p:inputText>.
In the dialog, I use an <iframe> and call a JS function to set the src of <iframe> and show the dialog. But I have no idea to update the <p:inputText> from an <iframe>.
Main page:
<h:form id="dialogForm">
<p:inputText id="tarText" value="" />
<p:commandButton value="master file" oncomplete="showDialog('#{request.contextPath}')" />
<p:dialog widgetVar="lookupDialog" header="Lookup">
<iframe id="myiframe"></iframe>
</h:form>
JS:
function showDialog(contextPath) {
var myiframe = document.getElementById("myiframe");
myiframe.src = contextPath + "/pages/lookup.xhtml";
lookupDialog.show();
}
Edit----
#BalusC but how can I refresh a special area of this page by pressing a button? The more important thing is, the different button pressed, the different content shown out. And I don't wanna refresh the page sync.

Resources