Primefaces p:messages dissappears after ajax call - jsf

My problem is that p:messages error message flashes and then dissappears. I understand that my ajax on h:commandButton clears the form but I need to keep the message inside the form and I cannot get my method to run in other ways I.E. p:commandButton onclick.
My xhtml code snippet from card.xhtml template:
<h:form id="cardForm">
<p:messages closable="true" id="msg">
<p:autoUpdate disabled="true"/>
</p:messages>
<h:commandButton
value="Add card to profile"
actionListener="#{cust.addCardToProfile('cards.xhtml')}"
rendered="#{not cart}">
<p:ajax oncomplete="addCardToProfile();" update=":cardForm:msg"/>
</h:commandButton>
<h:form>
How to correctly run my "addCardToProfile();" -method and update messages so it stays on the screen.
Original xhtml:
...
<p:remoteCommand name="addCard2OptionList"
actionListener="#{saml2IdPLoginController.addCard2OptionList}"/>
...
<p:outputPanel id="userCard">
<ui:define name="content">
<ui:include src="/WEB-INF/templates/card.xhtml"/>
</ui:define>
</p:outputPanel>
As suggested by #Melloware, It might have something to do with RemoteCommand component.

Related

JSF component is not rendered from my p:commandButton in in a dialog in included page

My page contains a login header that i include via ui:include. The included page contains a dialog with a p:commandButton. When the user logs in, the include page is refreshed properly according to the #form in the update attribute. I also want to update a component outside the included page, that shall display a button when the user is logged in. The include page refreshes and the name of the logged in user is displayed. But the button in the main page is not shown. It is displayed if I refresh the page though. I can't figure out what I'm doing wrong here. Anyone have any ideas.
The header page also displays the commandLink component properly. But when clicking the logout link, the button in the main page is not removed. Since the commandLink does not use ajax, I assume that a normal page POST is done. Which should reload the whole page. Doesn't this work from a page that have been referenced with ui:include?
The login page is using a session scoped backing bean. The main page is view scoped.
Here's the included xhtml (login.xhtml):
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<div style="width:100%;font-size:12px;line-height:20px;background-color:#b0d9e6;color:white">
<h:form>
<h:message id="top_msg"></h:message>
<h:panelGrid width="100%" columns="3" columnClasses="none,right1,right1">
<h:outputLink rendered="#{!loginController.loggedIn}" styleClass="text-align:right;" value="javascript:void(0)" onclick="PF('dlg').show();" title="login">
<p:outputLabel>Login</p:outputLabel>
</h:outputLink>
<h:commandLink rendered="#{loginController.loggedIn}" action="#{loginController.logout}" styleClass="text-align:right;" >
<h:outputLabel>Logout</h:outputLabel>
</h:commandLink>
<p:growl id="growl" sticky="true" showDetail="true" life="3000" />
<p:dialog header="Login" widgetVar="dlg" resizable="false">
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="username" value="Username:" />
<p:inputText id="username" value="#{loginController.username}" required="true" label="username" />
<h:outputLabel for="password" value="Password:" />
<p:password id="password" value="#{loginController.password}" required="true" label="password" />
<f:facet name="footer">
<p:commandButton value="Login"
update="#form :createform:createbutton"
actionListener="#{loginController.login}"
oncomplete="handleLoginRequest(xhr, status, args)" >
</p:commandButton>
</f:facet>
</h:panelGrid>
</p:dialog>
</h:panelGrid>
<script type="text/javascript">
function handleLoginRequest(xhr, status, args)
</script>
</h:form>
</div>
</ui:composition>
...
This one is included in the following main page:
...
<ui:include src="login.xhtml" />
<h:form id="createform">
<h:panelGroup id="createbutton" layout="block">
<p:commandButton id="createnew"
ajax="false"
action="#{recepieController.createNewRecipes}"
value="Create new recipe"
rendered="#{recepieController.loggedIn and !recepieController.create and !recepieController.viewOnly and !recepieController.edit}"
accesskey="s">
</p:commandButton>
</h:panelGroup>
</h:form>
You cannot rerender a non-rendered component. If you partially render a button, and the button is not rendered, you cannot call an update on that button, because it does not exist in the DOM.
You have to call the AJAX update on the parent naming container, that is ALWAYS rendered. Thus, update the :createform rather than the button inside. The form is always rendered, no matter what.
I found the issue. In my commandButton "createnew", I used the wrong value to render on.
<p:commandButton id="createnew"
ajax="false"
action="#{recepieController.createNewRecipes}"
value="Create new recipe"
rendered="#{recepieController.loggedIn and !recepieController.create and !recepieController.viewOnly and !recepieController.edit}"
accesskey="s">
</p:commandButton>
It should use my session scoped bean (loginController) to check if the user is logged in. Changing to the following works.
<h:panelGroup id="createbutton">
<p:commandButton id="createnew"
ajax="false"
action="#{recepieController.createNewRecipes}"
value="Create new recipe"
rendered="#{loginController.loggedIn and !recepieController.create and !recepieController.viewOnly and !recepieController.edit}"
accesskey="s">
</p:commandButton>
</h:panelGroup>
Note the difference rendered="#{loginController.login ...} instead of rendered="#{recepieController.loggedIn}"
The recepieController also has a loggedIn attribute which I set, but since the page is not re-posted I guess the value is not changed for the attribute when I login.
However, I believe I tested to use ajax="false" in the p:commandButton for the login dialog which I guess should reset the view scoped version of my loggedIn attribute. I don't fully understand why that didn't work.

How to refresh the page after closing p:dialog

I've the below dialog:
<h:form id="r1">
<p:commandButton value="Basic" type="button" onclick="PF('dlg1').show();" />
<p:dialog header="Basic Dialog" widgetVar="dlg1">
<h:outputText id="test" value="Welcome to PrimeFaces" />
</p:dialog>
</h:form>
How can I refresh the JSF page after closing the dialog?
The <p:dialog> supports the ajax close event. This only requires it being placed inside a <h:form> (on contrary to the general recommendation), so you need to make sure that it's already manually poisitioned to the very end of the <h:body> and that you don't make use of appendToBody.
<h:body>
<h:panelGroup id="content" layout="block">
...
</h:panelGroup>
...
<h:form>
<p:dialog>
<p:ajax event="close" update=":content" />
...
</p:dialog>
</h:form>
</h:body>
Use if necessary update="#all" if you intend to update the entire page. But better is to update only the parts which really need to be updated.

How to target entire JSF page to be blocked by p:blockUI / pe:blockUI?

The example demonstrates blocking of <h:form> by <pe:blockUI>.
<h:form id="form" prependId="true">
<pe:blockUI target="form" widgetVar="blockBodyUIWidget">
<h:panelGrid columns="2">
<h:graphicImage library="default" name="images/ajax-loader1.gif" class="block-ui-image"/>
<h:outputText value="#{messages['blockui.panel.message']}" class="block-ui-text"/>
</h:panelGrid>
</pe:blockUI>
<p:commandButton id="btnSubmit"
onstart="PF('blockBodyUIWidget').block()"
oncomplete="PF('blockBodyUIWidget').unblock();}"
update=":form:dataGrid" actionListener="#{bean.listener}"
icon="ui-icon-check"
value="Save">
</h:form>
This blocks <h:form> but there is a template with a header and a left side bar which are not blocked by doing so.
I have tried to block <h:body id="body"> <pe:blockUI target="body"... on the template page but that didn't work ending with an exception indicating, "Cannot find component with the id body in the view."
So, how to target the entire page?
Although I'm using <pe:blockUI> of PrimeFaces extension, the same thing can be demonstrated by <p:blockUI> of PrimeFaces
Give an id to your body and then reference it on the block argument of the <p:blockUI> component.
Example:
<h:body id="entirePage"/>
and
<p:blockUI id="blockUI" widgetVar="blockBodyUIWidget" block=":entirePage"/>

Primefaces dialogbox popup refreshes the background and disapears

I am using primefaces dialogbox for popup purpose. But everytime it gets opened the whole screen get refreshed automatically and the popup disappears.
< p:dialog id="dialog" header="Select different user" styleClass="atf-header" widgetVar="dlg" appendToBody="true">
<ui:include src="searchpopup.xhtml" />
</p:dialog>
<h:panelGroup>
<h:outputLabel value="#{I18N['Create_Ticket_for_other_users']}" styleClass="atf-header" style="width:600px"></h:outputLabel>
</h:panelGroup>
<h:panelGroup id="search_section" layout="block"
styleClass="atf-content-area atf-separarot-botton" style="width:600px">
<h:panelGroup id="input_search_section" >
<h:outputText id="name" value="Siddharth Mishra"
labelStyleClass="atf-label">
</h:outputText>
</h:panelGroup>
<h:panelGroup styleClass="atf-right atf-inline-block">
<p:commandButton id="btn_search" value="select different user"
styleClass="atf-button-search" onclick="dlg.show()">
</p:commandButton>
</h:panelGroup>
</h:panelGroup>
You p:commandButton is AJAX button (which is default in primefaces) which submits whole form. Add type="button" attribute to it so it will be just ordinary button which do some JavaScript (so called push button). Also I don't see where is h:form tag here. As you have appendToBody="true" in you p:dialog be shore that you don't encapsulate p:dialog inside h:form. You should have h:form inside p:dialog if it is necessary, and if it is not move p:dialog outside of h:form.

primefaces datatable selection issue

I have some weird issue with datatable selection (most likely i'm doing something wrong).
Idea is simple - datatable with selection and a dialog to edit the records. The problem is that if i use <h:inputText> tag (or <p:inputText>) it appears to be blank, though the object in the backing bean (indicatorBean.indicator.code) contains data. Interestingly if i put <h:outputText> instead of input the data is shown.
here are contents of my body
<!-- language: xml -->
<h:body>
<h:form id="form">
<p:growl id="messages" showDetail="true"/>
<p:dataTable id="indicatorsTable" var="ind"
value="#{indicatorBean.indicators}"
selectionMode="single"
selection="#{indicatorBean.indicator}"
rowKey="#{ind.id}">
<p:column headerText="Name" style="width:125px">
#{ind.name}
</p:column>
<p:column headerText="Code" style="width:125px">
#{ind.code}
</p:column>
<f:facet name="footer">
<p:commandButton id="viewButton" value="View"
icon="ui-icon-search" update=":form:display"
oncomplete="indDialog.show()"/>
</f:facet>
</p:dataTable>
<p:dialog id="dialog" header="Indicator Detail"
widgetVar="indDialog" resizable="false"
width="400" showEffect="fade" hideEffect="fade">
<h:panelGrid id="display" columns="2" cellpadding="4">
<h:outputText value="Code:"/>
<!-- PROBLEM IS HERE -->
<h:inputText value="#{indicatorBean.indicator.code}"/>
<h:outputText value="Name:"/>
<h:outputText value="#{indicatorBean.indicator.name}"/>
</h:panelGrid>
<p:commandButton value="Save" onclick="indDialog.hide()"/>
<p:commandButton value="Cancel" onclick="indDialog.hide()"/>
</p:dialog>
</h:form>
</h:body>
Backing bean is nothing other that accessors.
Another thing i spotted is if i replace el expression in <h:inputtext> with a static text (like <h:inputText value="static text"/>), it is shown.
Here are some pictures:
Dialog with inputtext
Dialog with outputtext
Dialog with static text
primefaces 3.4
The problem as you seem to have already figured out is that you are placing the dialog itself inside of a form. This is an issue because of the way the jQuery dialog control works, which is the client side foundation of the Primefaces dialog. Essentially it will move DOM elements associated with the dialog elsewhere, possibly outside of the form that you intend to enclose it.
This problem can be easily solved by putting the dialog outside of the form, and putting a form inside of the dialog body instead.
<p:dialog id="dialogId" ...>
<h:form id="dlgForm">
....
</h:form>
</p:dialog>
In this way when jQuery UI moves the dialog control elsewhere in the DOM, the contents of that DOM, including the form come with it.

Resources