I have command link inside an accordion inside of primefaces wizard and they're all in the same form - I don't have nested forms and yet the action of the command link is not fired.
Here's my page:
<ui:define name="content">
<h:form id="createSubject">
<p:wizard flowListener="#{createWizard.flowListener}" widgetVar="wiz" showNavBar="false">
<p:tab id="personal" title="#{createWizard.tab1Title}">
....
</p:tab>
<p:tab id="conclusion" title="#{createWizard.tab2Title}">
<p:panel header="#{createWizard.panel2Title}">
<p:accordionPanel value="#{createWizard.similarSubjects}" var="subject">
<p:tab title="#{subject.VPrenom} #{subject.VNom}">
<h:panelGrid columns="2" cellpadding="5">
<h:outputText value="#{createWizard.firstName}: " />
<h:outputText value="#{subject.VPrenom}" />
<h:commandLink value="#{createWizard.completeSheet}" actionListener="#{createWizard.completeSubjectSheet(subject.VIdPool)}"/>
</h:panelGrid>
</p:tab>
</p:accordionPanel>
</p:panel>
</p:tab>
</p:wizard>
<p:commandButton value="#{createWizard.nextButtonTitle}" onclick="wiz.next()" style="float:right;"/>
</h:form>
</ui:define>
and my backing bean method:
public void completeSubjectSheet(String subId){
mk.sdc.helpers.Link link = mk.sdc.helpers.Link.getLink();
try {
FacesContext.getCurrentInstance().getExternalContext().redirect(link.mkLink("/POOL/view.jsp?V_ID_POOL="+subId));
} catch (IOException ex) {
Logger.getLogger(CreateWizard.class.getName()).log(Level.SEVERE, null, ex);
}
}
Any ideas? Thanks.
Because actionListener can't take any arguments, you have to use action attribute for commandLink.
EDIT
Can you use h:link or h:outputLink for that?Like
<h:link outcome="/POOL/view.jsp?V_ID_POOL=#{subject.id}" />
Related
I am new to JSF/PrimeFaces and am trying to update a DataTable(SearchResultsTable) in my Dialog(SearchResultsDlg)from another Dialog(SearchDlg) I tried putting my List of Objects on the the FacesContext and I tried to make it the return type but Dialog(SearchResultsDlg) keeps popping up empty. No errors on the java side and I know I'm returning a List of type Object from my query. Here is snippits of code in the order in which they execute. Any ideas would be great!
Search.xhtml
<ui:composition>
<p:dialog id="SearchDlg"
widgetVar="SearchDialog"
modal="true"
resizable="false"
appendTo="#(body)" header="#{bundle.Search}">
<h:form id="SearchForm" >
<h:panelGroup id="SearchDisplay">
<p:panelGrid columns="2">
<p:outputLabel id="SearchLabel" value="What" />
<p:inputText id="SearchText" value="#{offerController.searchText}" size="40"/>
<p:outputLabel id="ZipCodeLabel" value="Where" />
<p:inputText id="postalcode" value="#{offerController.postalCode}" size="12"/>
</p:panelGrid>
<p:commandButton id="Search"
value="Search"
actionListener="#{offerController.search}"
onclick="handleSubmit(args, 'SearchDialog')" />
<p:commandButton value="#{bundle.Cancel}" onclick="SearchDialog.hide()"/>
</h:panelGroup>
</h:form>
</p:dialog>
</ui:composition>
OfferController.java
public List<Offer> search() {
List<Offer> offers = null;
try {
offers = getFacade().search(PostalCode, Distance, Category, SubCategory, SearchText, SearchType);
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("offer", offers);
RequestContext.getCurrentInstance().openDialog("SearchResult");
RequestContext.getCurrentInstance().update("SearchResultsTable");
} catch (Exception e) {
System.out.println(e);
}
return offers;
}
SearchResults.xhtml
<ui:composition>
<p:dialog id="SearchResultsDlg"
widgetVar="SearchResultsDialog"
modal="true"
resizable="false"
appendTo="#(body)"
header="#{bundle.Login}" >
<ui:define name="title">
<h:outputText value="#{bundle.ListOfferTitle}"></h:outputText>
</ui:define>
<ui:define name="body">
<h:form id="SearchResultsForm">
<p:panel header="#{bundle.ListOfferTitle}">
<p:dataTable id="SearchResultsTable" value="#{offerController.search}" var="offer"
selectionMode="single" selection="#{offerController.selected}"
paginator="true"
rowKey="#{offer.name}"
rows="10"
rowsPerPageTemplate="10,20,30,40,50">
<p:ajax event="rowSelect" update="createButton viewButton editButton deleteButton"/>
<p:ajax event="rowUnselect" update="createButton viewButton editButton deleteButton"/>
<p:column>
<f:facet name="header">
<h:outputText value="#{bundle.ListOfferTitle_sellerUserID}"/>
</f:facet>
<h:outputText value="#{offer.sellerUserID}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="#{bundle.ListOfferTitle_name}"/>
</f:facet>
<h:outputText value="#{offer.name}"/>
</p:column>
</p:dataTable>
</p:panel>
</h:form>
</ui:define>
</p:dialog>
</ui:composition>
Use selector for update:
p:dataTable id="SearchResultsTable" styleClass="for-update"
and button or ajax:
p:commandButton id="Search" update="#(.for-update)"
You have to reference the component you want to update from the component that tirggers the update action. For example if I want to update "dataTable1" contained in "dialog1" from "button2" contained in "dialog2":
<p:dialog id="dialog1" ... >
<h:form id="form1">
<p:dataTable id="dataTable1"...>
...
</p:dataTable>
</h:form>
</p:dialog>
<p:dialog id="dialog2" ... >
<h:form id="form2">
<p:commandButton
process="#form" update=":form1:dataTable1" />
</h:form>
</p:dialog>
I use PrimeFaces 5.0 and jsf 2.2. Here is my page that contains PrimeFaces tabview
<h:panelGroup layout="block" style="position:absolute;top:60px;width:100%;">
<p:tabView id="tabs" activeIndex="#{TabsManagerBean.activeIndex}" onTabShow="$('#tvlistr').click();" dynamic="true"
value="#{TabsManagerBean.tabs}" var="tab">
<p:ajax event="tabChange" listener="#{TabsManagerBean.onTabChange}" />
<p:tab title="#{tab}" titleStyle="width:180px" />
</p:tabView>
<p:commandLink id="tvlistr" style="display:none;" action="#{TabsManagerBean.navigate}"/>
</h:panelGroup>
My onTabChange method
public void onTabChange(TabChangeEvent evt) {
logger.debug("Tab changed to: {}.", evt.getData());
selectedTab = (String) evt.getData();
...
}
and the problem that this method isn't called. i need this method to be called before
<p:commandLink id="tvlistr" style="display:none;" action="#{TabsManagerBean.navigate}"/>
Updated: here is my h:form
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui">
<f:view locale="en">
<h:head>
<title>#{appMsg.common_pms}</title>
<!-- main JavaScript file -->
<h:outputScript name="js/main.js" />
</h:head>
<h:body>
<h:form id="formId" prependId="false">
<ui:include src="progressbar.xhtml" />
<h:panelGroup id="header" layout="block" style="position:absolute;top:0;width:100%;height:90px;">
<ui:include src="header.xhtml" />
</h:panelGroup>
<h:panelGroup layout="block" style="position:absolute;top:60px;width:100%;">
<p:tabView id="tabs" activeIndex="#{TabsManagerBean.activeIndex}" onTabShow="$('#tvlistr').click();" dynamic="true"
value="#{TabsManagerBean.tabs}" var="tab">
<p:ajax event="tabChange" listener="#{TabsManagerBean.onTabChange}" />
<p:tab title="#{tab}" titleStyle="width:180px" />
</p:tabView>
<h:commandLink id="tvlistr" style="display:none;" action="#{TabsManagerBean.navigate}">
<f:ajax event="action" />
</h:commandLink>
</h:panelGroup>
<h:panelGroup id="footer" layout="block" style="position:absolute;height:20px;width:100%;bottom:0;background-color: #005696">
<ui:include src="/templates/version.xhtml" />
</h:panelGroup>
</h:form>
</h:body>
</f:view>
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
This is likely a bug related to dynamically built tabs. Removing the "var" and "value" and presenting static tags will cause the listener to fire properly. Might want to file a bug report.
<p:tabView id="tabs" activeIndex="#{TabsManagerBean.activeIndex}" onTabShow="$('#tvlistr').click();" dynamic="true">
<p:ajax event="tabChange" listener="#{TabsManagerBean.onTabChange}" />
<p:tab title="First tab" titleStyle="width:180px" />
<p:tab title="Second tab" titleStyle="width:180px" />
</p:tabView>
I am trying to do a Primefaces On-Demand Loading tabbed panel component which has a inputTextArea component inside it. I follow this tutorial Primefaces Tutorial.
My .xhtml form looks like this:
<h:form>
<h:outputText
value="Write a comment" />
<p:tabView dynamic="true" cache="true">
<p:tab title="Possitive">
<h:panelGrid columns="2" cellpadding="10">
<p:inputTextarea rows="5" cols="130" />
</h:panelGrid>
</p:tab>
<p:tab title="Negative">
<h:panelGrid columns="2" cellpadding="10">
<p:inputTextarea rows="5" cols="130" />
</h:panelGrid>
</p:tab>
</p:tabView>
<p:commandButton value="Publish"></p:commandButton>
</h:form>
But these inputTextBox are always loaded, nevertheless i did not click on them. Can they be loaded only on demand and how to do this?
Thanks in advance for the help!
Primefaces builds JSF tree for all tabs. Both inputTextarea(s) are created on server side. It can be solved by ui:include. Put the content of p:tab into extra file and use ui:include to fetch the content:
<p:tabView>
<p:tab title="Possitive">
<ui:include src="#{tabViewBean.getTabSource('tabPositive')}"/>
</p:tab>
<p:tab title="Negative">
<ui:include src="#{tabViewBean.getTabSource('tabNegative')}"/>
</p:tab>
</p:tabView>
TabViewBean holds active tab name and is used for resolving tab sources as well. If a tab is NOT ACTIVE then the method tabViewBean.getTabSource() returns another file with EMPTY content:
public String getTabSource(String tabName)
{
return tabName.equals(activeTabName) ?
getTabSourceForTabName(tabName) :
"EmptyTab.xhtml";
}
public String getTabSourceForTabName(String tabName)
{
if ("tabPositive".equals(tabName)) return "TabPositive.xhtml";
if ("tabNegative".equals(tabName)) return "TabNegative.xhtml";
}
You should have EmptyTab.xhtml somewhere. Set listener in p:tabView to listen the tab change event :
<p:tabView listener="#{tabViewBean.tabChangeListener}">
tabChange listener sets the name of active tab:
public void tabChangeListener(UIComponentBase tabView)
{
activeTabName = getTabNameByIndex(tabView.getActiveIndex());
}
public String getTabNameByIndex(int index)
{
if (i==0) return "tabPositive";
if (i==1) return "tabNegative";
}
I have an xhtml page where I have put one <p:tabView> containing 3 <p:tab>.
In each <p:tab> I have one <p:ring>. Like this:
<p:tabView>
<p:tab id="tab1">
<p:ring/>
</p:tab>
<p:tab id="tab2">
<p:ring/>
</p:tab>
<p:tab id="tab3">
<p:ring/>
</p:tab>
</p:tabView>
The ring of the first tab (tab1) is displaying normally.. but for the 2 others (rings of tab2 and tab3), the ring items are displayed one over the other. And it's only when I click on some of its items that the original disposition is retrieved.
He is a screenshot of the abnormal display:
and the normal one (obtained when I click on an item):
Is there a problem in the ring combined with the tabView or am I missing something?
**EDIT: **
Here is the code of my xhtml page (the code of one tab actually):
<p:tab id="tabExec" title="Exécutable">
<p:growl id="displayE" showDetail="true" />
<h:form id="formDev">
<h:panelGrid columns="2">
<h:outputText value="Nom de l'exécutable: *" />
<p:inputText value="#{developerController.nomLivrable}"
label="Nom du livrable" required="true" />
<h:outputText value="Exécutable: *" />
<h:panelGroup layout="block">
<p:fileUpload fileUploadListener="#{ftpFileUpload.upload}"
description="Sélectionnez un fichier"
update=":BigTabView:displayE :BigTabView:formDev:outFileNameE"
style="margin-right: 20px;" required="true" label="Exécutable" />
<h:outputText id="outFileNameE"
value="#{ftpFileUpload.getFileName()}" />
</h:panelGroup>
<h:panelGroup layout="block">
<p:commandButton value="Valider"
actionListener="#{developerController.storeFile(developerController.nomLivrable)}"
update=":BigTabView:displayE :BigTabView:formDevs:historiqueDevsRing"
style="margin-right: 5px;" />
<p:commandButton value="Annuler" type="reset" />
</h:panelGroup>
</h:panelGrid>
</h:form>
<h:form id="formDevs">
<p:ring id="historiqueDevsRing"
value="#{developerController.executableList}" var="exec">
<p:graphicImage value="#{resource['images/exe.png']}"
height="100px" />
<p:commandLink value="#{exec.nomlivrable}"
actionListener="#{developerController.connectToFtpServer()}"
oncomplete="window.open('ftp://#{exec.emplacementlivrable}'); return false;"
update=":BigTabView:displayE">
</p:commandLink>
</p:ring>
</h:form>
</p:tab>
The problem resides on the fact that p:ring uses absolute position. In order to prevent this behavior (not the positioning, the "stacked" ring), you need to implement a tabChange event handler as follows, AFTER adding the forms:
<body>
<p:tabView>
<p:ajax event="tabChange" listener="#{bean.onTabChange}"/>
<p:tab id="tab1">
<h:form>
<p:ring value="#{bean.list}" var="st">
<p:outputLabel value="1#{st}"/>
</p:ring>
</h:form>
</p:tab>
<p:tab id="tab2">
<h:form>
<p:ring value="#{bean.list}" var="st">
<p:outputLabel value="2#{st}"/>
</p:ring>
</h:form>
</p:tab>
<p:tab id="tab3">
<h:form>
<p:ring value="#{bean.list}" var="st">
<p:outputLabel value="3#{st}"/>
</p:ring>
</h:form>
</p:tab>
</p:tabView>
</body>
In your managedBean:
#ManagedBean(name="bean")
public class BeanView implements Serializable {
private static final long serialVersionUID = 1775631010811130942L;
private List<String> list;
#PostConstruct
public void init() {
list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
}
public void onTabChange(TabChangeEvent event){
Tab selected = event.getTab();
for (UIComponent comp : selected.getChildren())
if (comp instanceof HtmlForm)
for (UIComponent comp2 : comp.getChildren())
if (comp2 instanceof Ring){
//first solution, primefaces update
RequestContext.getCurrentInstance().update(comp2.getClientId());
//second solution, jquery click
FacesContext faces = FacesContext.getCurrentInstance();
String separator = UINamingContainer.getSeparatorChar(faces) + "";
String usingId = comp2.getClientId().replaceAll(separator, "\\\\\\\\" + separator);
RequestContext.getCurrentInstance().execute("$('#" + usingId + " li').last().click();");
}
}
public List<String> getList() {
return list;
}
This example works and the rings get updated on every tab change, the answer is based on the comment OP made.
This however, will bring your p:ring into a default state. For example, if my ring contains 5 values as:
data0 data1 data2 data3 data4
the first item displayed on the ring is data0. If I select data3, change tabs, reopen the same tab with the ring inside then data0 will be displayed. To prevent this behavior, you need to implement a selection into your managedBean (f:setPropertyActionListener is your best bet).
i have a serious problem with jsf tabview and form
inside my tabview i have to input text and submit button whenever i submit i always have a empty value.
<h:form id="form">
<p:tab id="tabview" title="Ressources Humaines">
<p:tabView activeIndex="#{SelectBean.activeTab}" value="#{SelectBean.types}" var="item" >
<p:ajax event="tabChange" listener="#{SelectBean.onTabChange}" update=":form" />
<p:tab title="#{item}">
<p:tabView id="tab" activeIndex="#{SelectBean.other}" value="#{SelectBean.res}" var="rr">
<p:ajax event="tabChange" listener="#{SelectBean.onTabChange1}" />
<p:tab title="#{rr.nom_ressource}">
<p:panel rendered ="#{SelectBean.bol}" closable="true" toggleable="true" styleClass="outPanel">
<p:growl id="growl" showDetail="true" />
<h:outputLabel value="Nom " />
<h:inputText value="#{SelectBean.nom}" />
<br/>
<h:outputLabel value="Experience " />
<h:inputText value="#{SelectBean.exp}" />
<br/>
<h:commandButton immediate="true" value="Modifier" action="#{SelectBean.ok}"/>
</p:panel>
</p:tab>
</p:tabView>
</p:tab>
</p:tabView>
</h:form>
the SelectBean.nom and SelecBean.exp are always empty any help please
The problem is with your
<h:commandButton immediate="true" value="Modifier" action="#{SelectBean.ok}"/>
The immediate attribute action method causes JSF to go directly to the render phase 'of the same view' by calling facesContext.renderResponse(), then the components will behave as they do for a validation failure - by displaying the value cached in the component rather than fetching data from the backing bean.
Here is a list of possible solutions