well first ill explain what im tryng to do, i have a index.xhtml page where i include menu.xhtml with a menubar of primefaces, in menu.xhtml in have a panel id=contenido where i want to update depending of the menuitem clicked, i already get update that panel but the problem is when i update to another page for example in default is home.xhtml and i update to enviarsol.xhtml then the command button from enviarsol.xhtml is not working, im new at this and i already tried some different ways of updating the panel, im thinking that the problem is that the bean of enviarsol.xhtml is not managed or something like that,also im doing this way because i want to refresh only that panel and not all the page, someone help me please.
index.xhtml:
<h:form>
<img src="resources/homeheader.jpg" width="300" height="113" alt="homeheader"/>
<div style="background-color: white">
<img src="resources/Logos.jpg" width="1024" height="166" alt="homeheader"/>
</div>
<p:panel id="centerpage" >
<ui:include src="WEB-INF/menu.xhtml"/>
</p:panel>
</h:form>`
menu.xhtml:
<p:menuitem value="Contactos" icon="ui-icon-arrowreturnthick-1-w" actionListener="#{bnmenu.btnEditarContacto(e)}" update="contenido"/>
<p:panel id="contenido" >
<ui:include src="#{bnmenu.url}"/>
</p:panel>
bnmenu.java:
private String url;
public bnmenu() {
url="home.xhtml";
}
public void btnEditarContacto(ActionEvent e)
{
url="enviarsol.xhtml";
}
home.xhtml:
<p:panelGrid columns="2" style="border-width: 0px">
<p:commandButton value="Consultar" actionListener="#{bnhome.btnlogin(e)}" update="txt1"/>
<p:inputText id="txt1" value="#{bnhome.txtUsuario}"/>
</p:panelGrid>
enviarsol.xhtml:
<p:panelGrid columns="2" style="border-width: 0px">
<p:outputLabel for="txtcorreo" value="Correo: "/>
<p:inputText id="txtcorreo" value="#{bnSolicitud.correo}"/>
<p:outputLabel for="txtmensaje" value="Mensaje: "/>
<p:inputText id="txtmensaje" value="#{bnSolicitud.mensaje}"/>
<p:commandButton value="Enviar" actionListener="#{bnSolicitud.btnSolicitar(e)}" update="messages"/>
</p:panelGrid>`
i included this:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
and now it is working but i dont know what more effects will this cause
well now it works but only once when i click in commandbutton from enviarsol.xhtml
Finally it appears working fine, i changed #RequestScoped by #SessionScoped in bnmenu
Are you sure that you really want ajax navigation? It is very frustrating for a user not being able to use the browsers urlfield or navigation buttons, and it will be harder for you to code aswell. Consider transforming index.xhtml into a template file as described at http://www.mkyong.com/jsf2/jsf-2-templating-with-facelets-example and using normal navigation.
Related
I have a jsf page that adds an order from a client.
All works fine except when I click the commandLink to show the p:dialog to add a new client the update on the "reste" inputtext stop working (even if I close the p:dialog without adding the new client) :
Clients List :
<strong>Client :</strong><
<p:autoComplete
id="client"
value="#{venteSolaireBean.client}"
completeMethod="#{venteSolaireBean.autocompleteClient}"
var="item"
itemLabel="#{item.nom} #{item.prenom}"
itemValue="#{item}"
converter="#{venteSolaireBean.clientConverter}"
dropdown="true"
scrollHeight="200" >
</p:autoComplete>
Link to a p:dialog to add a new Cleint :
<p:commandLink onclick="dlgClient.show()" immediate="true">
<img src="images-main/add-icon.gif" border="0" alt="Add Client" class="img-action"/>
</p:commandLink>
Three p:inputtext items with ajax behavior :
<strong>Montant :</strong>
<p:inputText value="#{venteSolaireBean.venteSolaire.montant}">
<p:ajax event="keyup" update="reste" listener="#{venteSolaireBean.calcul}" />
</p:inputText>
<strong>Avance :</strong></td>
<p:inputText value="#{venteSolaireBean.venteSolaire.avance}">
<p:ajax event="keyup" update="reste" listener="#{venteSolaireBean.calcul}" />
</p:inputText>
<strong>Reste :</strong></td>
<p:inputText id="reste" value="#{venteSolaireBean.venteSolaire.reste}">
</p:inputText>
The venteSolaireBean.calcul function to execute with the listener :
public void calcul() {
venteSolaire.setReste(venteSolaire.getMontant() - venteSolaire.getAvance());
}
I checked by logging the calcul() function and I'm sure it was invoked and the value giving to setReste() is correct.
I don't see why inputtext didn't update.
please help.
I think that there are some problems with the validation. As immediate=true often leads to such problems and you are not using any primefaces-functionality on the button to show the dialog, you should replace the p:commandButton with a plain HTML button to show the "add client"-dialog.
I've stumbled upon a strage behavior of richfaces. Some background about my view structure:
It's mainly a <rich:extendedDataTable> where a click on a row displays info about it on a <a4j:outputPanel>
Also, each row has a context menu with items like "Create", "Edit", etc... that pops a <rich:popupPanel>
The component structure is this:
<h:panelGrid columns="2">
<h:column>
<rich:dataScroller for="testTable" maxPages="7"/>
<rich:extendedDataTable id="testTable" value="#{testController.items}" rendered="#{testController.items.rowCount != 0}"
selection="#{testController.selectedRow}" noDataLabel="No results to show" var="test" rows="20"
style="width: 790px" selectionMode="single">
<a4j:ajax execute="#form"
event="selectionchange"
listener="#{testController.selectionListener}"
render=":res"/>
{columns to display}
</rich:extendedDataTable>
</h:column>
<a4j:outputPanel id="res">
<rich:panel header="Selected Rows:" rendered="#{not empty testController.selectedRows}">
<rich:list type="unordered" value="#{testController.selectedRows}" var="t">
<h:outputText value="#{t.name}"/>
<br/>
<h:outputText value="#{t.details}" converter="#{testConverter}"/>
</rich:list>
</rich:panel>
</a4j:outputPanel>
</h:panelGrid>
<rich:contextMenu target="testTable" mode="ajax" id="contextMenu">
<rich:menuItem label="Edit" render="popupEdit" oncomplete="#{rich:component('popupEdit')}.show();" mode="ajax"/>
</rich:contextMenu>
<rich:popupPanel id="popupEdit" modal="true" autosized="true" resizeable="false" moveable="false" domElementAttachment="form">
<rich:hotKey key="esc" onkeyup="#{rich:component('popupEdit')}.hide(); return false;"/>
<f:facet name="header">
<h:outputText value="Edit Test"/>
</f:facet>
<f:facet name="controls">
<h:outputLink value="#" onclick="#{rich:component('popupEditar')}.hide(); return false;">
<h:graphicImage value="/resources/css/images/fechar_janela.png" width="20" height="20"/>
</h:outputLink>
</f:facet>
<h:panelGrid id="popupEditContent" columns="2">
... {display of info}
<a4j:commandButton value="Salvar" actionListener="#{testeController.update()}" render="tabelaTestes, contextMenu"/>
<h:panelGroup id="messagePanel" layout="block">
<rich:messages ajaxRendered="true" />
</h:panelGroup>
</h:panelGrid>
</rich:popupPanel>
And now the strange behaviour (using NetBeans):
Deploy the app from NetBeans;
Open the URL of the deployed project on browser (Firefox) . The <a4j:ajax> inlined in the table doesn't work, I know this because the 'testController.selectionListener' is not called and the details are not displayed (it sets the attribute current in the backing bean). The contextMenu works but the popupPanel shows null or empty properties in all fields (the current attribute is not set);
Go back to the IDE, remove all the <rich:popupPanel> section and save the file;
Back in the browser, hit F5 and click a row. Now the <a4j:ajax> works and calls testController.selectionListener, showing the details in <a4j:outputPanel>. The context menu works but (obviously) the panel does not pop;
In the IDE, put back the <rich:popupPanel> section and save the file;
Now refresh the page again, and everything works, details are shown and the Edit pop up shows the right info of the selected row.
I have tried deploying it without the <rich:popupPanel> section and the selecionListener gets called. I think that the problem is deploying the page with both <a4j:ajax> and <rich:popupPanel> sections, hence the "conflict".
I took the structure from the richfaces showcase and made changes. I noticed that in the showcase, the <rich:popupPanel> is placed outside the <h:form> tag, wich in my project is placed in the template.xhtml (so a topmenu page works). Is it possible that the error is caused by this placement?
Could this be considered a bug to file in the richfaces project or am I missing something there?
Is there a workaround or solution?
Thank you very much!
I think I have solved it. I set the id attribute to "form" in the <h:form> tag, in template.xhtml, so now it looks like this:
<h:body>
<h:form id="form">
<div id="top" class="top">
<ui:insert name="top">Top</ui:insert>
</div>
<div id="content" class="center_content">
<ui:insert name="content">Content</ui:insert>
</div>
</h:form>
</h:body>
It was the only change I made and now all the components work at first post-deploy.
Edit: Found the solution when searching for another problem: JSF action call on secon click
I have two p:dialog. Each one contains some input fields which are marked as required. Only one dialog is shown at a time but when I submit on any of the dialog, JSF also validates the input fields of the dialog which is not shown. What is the best approach to skip the validations in JSF 2 for the dialog which is not shown. One approach could be that I set the required="condation". But dont know what that condition could be and is it goin to work.
Each dialog is initially hidden. Each one has its own button to show. When one is active and I click the save button there is a validation error even when the required field has values. The validation error comes from the inactive dialog panel. May be it give some idea what i am trying to do.
UPDATE
<p:dialog header="Edit Group" widgetVar="dialog_groupEdit" resizable="false"
width="300" showEffect="bounce" hideEffect="explode" modal="true" position="center">
<h:panelGrid id="panel_groupEdit" columns="2">
<h:outputText value="Group Name: "/>
<h:inputText id="input_gnameEdit" size="26" value="#{groupBean.selectionGroup.gname}" required="true" requiredMessage="Edit Group: Name is required."/>
<h:outputText value="Description:"/>
<h:inputTextarea rows="6" cols="23" value="#{groupBean.selectionGroup.description}"/>
<div></div>
<p:commandButton value="Save" action="#{groupBean.saveGroupChanges}" oncomplete="#{args.validationFailed ? '':'dialog_groupEdit.hide()'}"
update="panel_groups panel_groupEdit" style="float:right;"/>
<div></div>
<p:message for="input_gnameEdit"/>
</h:panelGrid>
</p:dialog>
<p:dialog header="New Group" widgetVar="dialog_groupCreate" resizable="false"
width="300" showEffect="bounce" hideEffect="explode" modal="true" position="center">
<h:panelGrid id="panel_groupCreate" columns="2">
<h:outputText value="Group Name: "/>
<h:inputText id="input_gnameCreate" size="26" value="#{groupBean.createGroup.gname}" required="true" requiredMessage="New Group: Name is reqired."/>
<h:outputText value="Description:"/>
<h:inputTextarea rows="6" cols="23" value="#{groupBean.createGroup.description}"/>
<div></div>
<p:commandButton value="Save" actionListener="#{groupBean.saveGroupCreate}" oncomplete="#{empty groupBean.createGroup.gname ? ' ':'dialog_groupCreate.hide()'}"
update="panel_groupCreate panel_groups" style="float:right;"/>
<div></div>
<p:message for="input_gnameCreate"/>
</h:panelGrid>
</p:dialog>
One approach could be that I set the required="condation".
This is going to be clumsy. Just put each individual form in its own separate <h:form> component, or use the process attribute of the <p:commandButton> to identify the region you'd like to process.
<p:commandButton process="panel_groupEdit" ... />
...
<p:commandButton process="panel_groupCreate" ... />
Having a "God" form is in any way a poor practice.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?
When you are using <p:dialog some of the good practices as advised on the PF forum are -
Never put your <p:dialog inside any other component. Place it somewhere so that it falls right under the <h:body.
Give every <p:dialog it's own form. But, don't place the dialog inside the form, place the form inside the dialog. It's not good to update the dialog itself, only it's content. (I think this should solve your issue also.)
e.g.
<p:dialog widgetVar="dlg" ...
<h:form ...
<h:panelGroup id="dlgContent" ...
i have been struggling getting this to work for 2 weeks, I am trying to merge info from BalusC from these 2 posts to (link1 link2) to achieve partial page rendering of a center content area via a menu on the left. So the links on the left would update the center content via partial page rendering using <f:ajax> or maybe <a4j:ajax> via richfaces
------------------------------------------------------
| include1 link | |
| include2 link | center content like include1.xhtml |
| include3 link | |
------------------------------------------------------
my page-layout.xhtml (master template to be used by include1.xhtml, include2.xhtml,..)looks like this.
<h:body>
<div id="top" class="top">
<ui:insert name="top">page-layout default top content</ui:insert>
</div>
<div>
<div id="left">
<h:form id="navigationFormId">
<f:ajax render=":contentForm">
<h:commandLink value="include1"
action="#{navigationBean.setPage('include1')}" />
<p></p>
<h:commandLink value="include2"
action="#{navigationBean.setPage('include2')}" />
<p></p>
<h:commandLink value="include3"
action="#{navigationBean.setPage('include3')}" />
<p></p>
</f:ajax>
</h:form>
</div>
<div id="content">
<ui:insert name="content">
<h:panelGroup id="contentPanelGroup" layout="block">
<h:form id="contentForm">
<h:panelGroup rendered="#{navigationBean.page == 'include1'}">
<ui:include src="include1.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{navigationBean.page == 'include2'}">
<ui:include src="include2.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{navigationBean.page == 'include3'}">
<ui:include src="include3.xhtml" />
</h:panelGroup>
</h:form>
</h:panelGroup>
</ui:insert>
</div>
</div>
</h:body>
NavigationBean.java is defined as a ViewScoped bean via CDI with #Named
public class NavigationBean implements Serializable {
public NavigationBean() {}
public String getPage() {return page;}
public void setPage(String p) {page = p;}
private String page = "include1";
}
the included pages are file like include1.xhtml and include2.xhtml and should be loaded into center content when the left menu links are clicked, here is a sample include2.xhtml
<h:body>
<ui:composition template="page-template.xhtml">
<ui:define name="content">
include2
<h:form>
form components for include2
</h:form>
</ui:define>
</ui:composition>
</h:body>
I am getting FileNotFoundException, although the stack trace does not
tell which one, but removing the
<h:panelGroup rendered=".....>
<ui:include src="..." />
</h:panelGroup>
tags removes the exception. I think this is the proper implementation to accomplish this based on 2 of BalusC posts, but just can't get it to work.
The error you are getting suggests the include...xhtml page can not be found. Where are the files located? They should be in the same directory as the page-layout.xhtml file? To simplify everything I would just test if the include works, yuo can replace this:
<h:form id="contentForm">
<h:panelGroup rendered="#{navigationBean.page == 'include1'}">
<ui:include src="include1.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{navigationBean.page == 'include2'}">
<ui:include src="include2.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{navigationBean.page == 'include3'}">
<ui:include src="include3.xhtml" />
</h:panelGroup>
</h:form>
with:
<h:form id="contentForm">
<ui:include src="include1.xhtml" />
</h:form>
i was able to get a design via JSF2/Ajax and richfaces4 (other implementations would be ok I assume) where a left navigation menu item, implemented via templates, is able to render the center content of a template via ajax, preventing a full page refresh, and the flicker effect it has.
my navigationmenu.xhtml code looks like this
<ui:composition>
<h:form id="navigationFormId">
<rich:collapsiblePanel id="carrierCollapsibleId" header="Links that update center content" switchType="client">
<h:commandLink id="linkId1" action="/page1" value="Update Center Content with page1">
<a4j:ajax execute="#form" render=":centerContentDiv,:centerForm" />
</h:commandLink>
<br />
<h:commandLink id="linkId2" action="/page2" value="Update Center Content with page2">
<a4j:ajax execute="#form" render=":centerContentDiv,:centerForm" />
</h:commandLink>
</rich:collapsiblePanel>
...
</h:form>
I believe the render=":centerContentDiv,:centerForm" attribute for the a4j:ajax tags can be changed to just render=":centerForm" but have not tested that. I know the both work together however. also, i tried JSF2 ajax tags with white space between the IDs and got errors, so i went to richfaces 4.x's a4j and then could use commas if no space was used.
now, in order for this to work, each pageX.xhtml file, for example page1.xhtml would need to have <h:form id="centerForm">, here is an example of page1.xhtml
<ui:composition template="/templates/uiTemplate.xhtml">
<ui:define name="center_content">
<h:form id="centerForm">
<!-- put your components in here -->
</h:form>
</ui:define>
</ui:composition>
one limitation is each view that uses the template must define a <h:form id=centerForm" ...> otherwise JSF2 will complain it can't find the render target.
my uiTemplate.xhtml file has code for the header, footer, but the pertinent part that has the navigation and center content defined is as follows
<div class="header_content">
<div id="left">
<ui:include src="navigationMenu.xhtml" />
</div>
<div id="center_content">
<!-- think this panelGroup wrapper can be -->
<!-- removed. need to test that though -->
<h:panelGroup id="centerContentDiv" layout="block">
<ui:insert name="center_content" />
</h:panelGroup>
</div>
</div>
I have this xhtml code:
<p:dataGrid id="dgData"
columns="1"
rows="100"
value="#{myStickiesController.items}"
var="sticky">
<p:panel header="From :#{sticky.users.displayName}" rendered="#{eventstickiesController.eventSticky}" binding="#{eventstickiesController.eventPanel}">
<f:attribute name="stickyId" value="#{sticky.stickyID}" ></f:attribute>
<h:panelGrid columns="2">
<p:graphicImage value="#{imageStreamer.fileContent}" style="width:50px; height: 50px" alt="No Profile Image">
<f:param id="uid" name="uid" value="#{sticky.users.userID}" />
</p:graphicImage>
<h:outputLabel value="Event Info : #{eventstickiesController.content}" binding="#{eventstickiesController.outputLabel}">
<f:attribute name="stickyId" value="#{sticky.stickyID}" ></f:attribute>
</h:outputLabel>
</h:panelGrid>
<f:facet name="footer">
<p:commandButton image="/images/buttons/Delete.gif"
actionListener="#{myStickiesController.deleteSticky}"
action="#{snippetsStickyEditorLinkerBean.updateSnippetLink}"
update="dgData" >
<f:attribute name="stickyId" value="#{sticky.stickyID}" ></f:attribute>
<f:param name="pageViewId" value="Default"/>
</p:commandButton>
</f:facet>
</p:panel>
</p:dataGrid>
the code of the actionListener class:
public class MyStickiesController {
public void deleteSticky(ActionEvent ae)
{
Long sid = (Long)ae.getComponent().getAttributes().get("stickyId");
Stickies s = ejbFacade.find(sid);
List<Recipients> rl = s.getRecipientsList();
DBConnectionProxyUser sbcpu = new DBConnectionProxyUser();
Users currentUser = sbcpu.getConnectedUser(ejbUsersFacade);
for (Recipients r:rl)
{
if (currentUser.getUserID()==r.getUsers().getUserID())
{
r.setDisplay(Boolean.FALSE);
}
}
}
}
Now, if I put the command button that is inside the p:dataGrid, the dataGrid is updated and the actionListener works. If I put the button inside the dataGrid, the dataGrid is not updated and the actionListener doesn't work.
I tried wrapping thw whole thing with p:outputPanel, and the actionListener doesn't work.
The ActionEvent is javax.faces.event.ActionEvent
I am using Mojarra 2.1.3 with primefaces 2.2.1, Glassfish 3.0.1 and Netbeans 6.9.1
Thanks in advance...
I managed to make it work...
The solution renders into 2 parts:
I updated the Glassfish Mojarra Module to 2.1.3
I added a p:remotecommamd and a p:outputpanel to be rendered in case the inner snippet is to be rendered. Other snippets are easy to be rendered.
I hope this one helps somebody...