primefaces dialog disappears after show up when click commandLink - jsf

I have this code :
<h:form>
<h:commandLink value="Créer un compte" onclick="dlg3.show();"/>
</h:form>
<p:dialog id="modalDialoog" widgetVar="dlg3" draggable="false" resizable="false" dynamic="true" header="Inscription">
<center>
<p:panel id="xyzBody">
<h:form id="inscri-f">
<h:panelGrid id="loginPan" columns="2" bgcolor="White">
<h:outputText value="Nom d'utilisateur :" />
<p:inputText id="username" value="#{demandeBean.login}"></p:inputText>
<h:outputText value="Mot de passe :" />
<p:password id="pwd" value="#{demandeBean.pwd}"/>
<h:commandButton value="Envoyer demande" update=":inscri-f:cr"
actionListener="#{demandeBean.envoi_dde}"></h:commandButton>
<h:commandButton value="Retour" action="page1?faces-redirect=true"></h:commandButton>
<p:outputPanel id="cr">
<h:outputText rendered="#{demandeBean.saved}" value="#{demandeBean.message}"/>
</p:outputPanel>
</h:panelGrid>
</h:form>
</p:panel>
</center>
</p:dialog>
my problem is when I click commandLink "Créer un compte" dialog is shown and it disappears quickly.

This happens because <h:commandLink> executes a submit on the form that will be send the data to the server, the server will process the request, the server will generate a response and send it to client, thus getting the refresh behavior in browser.
Easy fix (for this scenario), add return false; at the end of the onclick to stop the form submission.
<h:commandLink value="Créer un compte" onclick="dlg3.show(); return false;"/>
As stated in BalusC comment, it would be easier to not have a <form> to begin with, so just using a plain <a>:
<a onclick="dlg3.show();">Créer un compte</a>

You can also use <p:commandlink ...oncomplete="dlg3.show();" /> instead of <h:commandlink onclick =.... />
It will ensure setting values in backing bean

Related

Primefaces modal not updating

Hi I've been stuck for sometime getting a modal form to update, it's loading the data, and it's calling the function - it's just not passing the data back to the server
<h:form id="modal">
<p:dialog widgetVar="modalText" styleClass="modalSceneText" modal="true" dynamic="true" >
<p:panel id="sceneText">
<p:inputTextarea id="sceneName" immediate="true" style="width: 200px" rows="1" counter="labelCount" maxlength="20" counterTemplate="{0} characters remaining." value="#{CustomerDashboardController.selectedScene.title}"/><h:outputText id="labelCount" /><br/>
<p:inputTextarea id="sceneDescription" immediate="true" rows="10" cols="50" value="#{CustomerDashboardController.selectedScene.description}" counter="descriptionCount" maxlength="1000" counterTemplate="{0} characters remaining." autoResize="false" /><br/>
<h:outputText id="descriptionCount" />
</p:panel>
<p:ajax event="close" process="#form" immediate="true" update=":form:locationScenes" listener="#{CustomerDashboardController.saveSelectedScene()}" />
</p:dialog>
</h:form>
I've tried it inside and outside the form, I've tried everything I can think off..
The sceneName & sceneDescription are loading the correct data, they're just not saving any changes when the modal/dialog is closed. saveSelectedScene() is being called fine.
EDIT
I can get it to save with a
<p:commandLink value="save" action="#{CustomerDashboardController.saveSelectedScene()}"/>
Which isn't very pretty. Seems the problem is trying to save on the close event.
Your problem here is that the saveSelectedScene() method which is called from the listener in the ajax component is using the old values of the inputTextarea's.
As a workaround you can use a remoteCommand component and call that on your close event instead:
<h:form id="modal">
<p:remoteCommand name="rc" update=":form:locationScenes" actionListener="#{CustomerDashboardController.saveSelectedScene()}" />
<p:dialog widgetVar="modalText" styleClass="modalSceneText" modal="true" dynamic="true" >
<p:panel id="sceneText">
<p:inputTextarea id="sceneName" immediate="true" style="width: 200px" rows="1" counter="labelCount" maxlength="20" counterTemplate="{0} characters remaining." value="#{CustomerDashboardController.selectedScene.title}"/><h:outputText id="labelCount" /><br/>
<p:inputTextarea id="sceneDescription" immediate="true" rows="10" cols="50" value="#{CustomerDashboardController.selectedScene.description}" counter="descriptionCount" maxlength="1000" counterTemplate="{0} characters remaining." autoResize="false" /><br/>
<h:outputText id="descriptionCount" />
</p:panel>
<p:ajax event="close" process="#form" immediate="true" oncomplete="rc()" />
</p:dialog>
</h:form>
Also consider if the immediate="true" are really necessary in your code
Have you tried removing immediate="true" from both input elements and p:ajax tag? It seems to me that you don't need it - especially not on p:ajax tag.
Hope this helps!

p:dialog appears on bottom when p:blockUI targets it

I have a PrimeFaces dialog, that has two command buttons that executes some code in the backing bean. I want to block the dialog within the action.
I managed to do it using blockUI, but when the blockUI is present, and I open the dialog, it appears at the bottom of the page.
If I remove the blockUI component, the dialog opens at the center of the page, as I want. But I want it to be centered and with the blockUI.
<p:dialog header="Attention" id="dialog" position="center"
widgetVar="dialog" modal="true" closable="false"
dynamic="true" closeOnEscape="false">
<div class="internal-margin-top">
<h:outputText value="Location" styleClass="ui-outputtext" />
<p:inputText value="#{activityBean.location}"
id="inputLocation" maxlength="15">
</p:inputText>
</div>
<div class="internal-margin-bottom">
<p:commandButton id="closureYes" value="Yes"
styleClass="btn-green"
onstart="PF('block').show();"
oncomplete="PF('dialog').hide(); PF('block').hide();"
action="#{activityBean.processItem()}" process="#all">
</p:commandButton>
<p:commandButton id="closureNo" value="No"
styleClass="btn-red"
onstart="PF('block').show();"
oncomplete="PF('dialog').hide(); PF('block').hide();"
action="#{activityBean.processActivity()}" process="#all" />
</div>
</p:dialog>
<p:blockUI block="scrapDialog" widgetVar="block">
<p:graphicImage library="images" name="loading_bar.gif" />
</p:blockUI>
Thanks in advance.
Example with a centered modal dialog:
<p:dialog header="Header" position="center" widgetVar="wv_dialog" modal="true" closable="false" dynamic="true" closeOnEscape="false">
<h:form id="dialogform">
<p:panelGrid columns="1">
<p:inputText value="test"/>
<p:inputText value="test"/>
<p:inputText value="test"/>
<p:inputText value="test"/>
</p:panelGrid>
<p:commandButton id="closebutton"
value="Close"
oncomplete="PF('wv_dialog').hide();"
action="#{testBean.actionTest()}"
process="#form"/>
<p:blockUI block="dialogform" trigger="closebutton"/>
</h:form>
</p:dialog>

Getting a NullPointerException while Partial rendering via FacesContext

I have a strange behavior where I am getting NPE while doing page refresh using faces context.
I have a managed bean which is in Request Scope. So want to refresh the page after click on commandbutton. I have tried with 'update' but it is behaving strange in my page.
Error: PartialViewContextImpl$PhaseAwareVisitCallback.visit : java.lang.NullPointerException
This is my JSF page:
<h:form id="form">
<p:messages autoUpdate="true"/>
<h:panelGrid columns="4" cellpadding="5" id="panelGrid" rendered="true">
<p:outputLabel for="s00" value="#{tk.expense_keyword}"/>
<p:inputText id="s00" value="#{expense.form.keyword}"/>
<p:outputLabel for="s02" value="#{tk.expense_creatorId}"/>
<p:inputText id="s02" value="#{expense.form.creatorId}" disabled="#{!expense.form.canEditCreatorId}"/>
<h:outputText id="s10" value="Amount Between #{expense.form.amountFrom} and #{expense.form.amountTo}" />
<h:panelGrid>
<p:slider for="s11,s12" display="s10" minValue="0" maxValue="1000" style="width: 200px" range="true" displayTemplate="Amount Between {min} and {max}" />
<h:inputHidden id="s11" value="#{expense.form.amountFrom}" />
<h:inputHidden id="s12" value="#{expense.form.amountTo}" />
</h:panelGrid>
</h:panelGrid>
<p:commandButton value="#{tk.expense_search}" id="a01" action="#{expense.search}" ajax="false" immediate="true"/>
<p:dataTable var="line" varStatus="loop" value="#{expense.form.expenseEntryList}" emptyMessage="#{tk.expense_table_empty}" id="dataTable">
<p:column headerText="#{tk.expense_table_creatorId}">
<h:inputHidden value="#{line.oid}"/>
<h:inputText value="#{line.creatorId}"/>
</p:column>
<f:facet name="footer">
<p:commandButton value="#{tk.expense_saveAsDraft}" id="a06" action="#{expense.saveAsDraft}"/>
<p:commandButton value="#{tk.expense_submit}" id="a07" action="#{expense.submitAll}"/>
<p:commandButton value="#{tk.expense_validate}" id="a08" action="#{expense.validate}"/>
</f:facet>
</p:dataTable>
</h:form>
Here when I click on Save As Draft I want to refresh the page. So I am using FacesContext's method to refresh the page.
Here is my method saveAsDraft:
public Outcome saveAsDraft() throws Exception{
try {
saveAsDraftBody(false,false);
getFacesContext().getPartialViewContext().getRenderIds().add("form:panelGrid");**//**getting error****
getFacesContext().getPartialViewContext().getRenderIds().add("form:dataTable");**//**works fine****
Log.info(this,"getFacesContext().getPartialViewContext().getRenderIds(): "+getFacesContext().getPartialViewContext().getRenderIds());
return Outcome.SUCCESS;
}
catch (Throwable e){
throw manageError(e);
}
}
I don't know why it works for data table refresh but not for panelGrid :(
First of all you have the bean in request scope and you are making full page submit and here the partial render does not make any sense. The error you are getting because you have component which is basically, another input into a form which will be sent to the managed bean of the current view when the form is submitted.

Primefaces Confirm Message Updated Value

I'm trying to show an updated value in confirm dialog message but I keep getting the old value as in this scenario
<h:form>
<p:inputText value="#{bean.object.amount}"/>
<p:commandButton value="CALCULATE" update="cal" actionListener="#{bean.calculate()}"/>
<h:panelGroup id="cal">
<h:outputText value="#{bean.object.amount}"/>
<p:commandButton value="SUBMIT" actionListener="#{bean.submit()}">
<p:confirm header="Confirmation" message="Amount is : #{bean.object.amount} ?"/>
</p:commandButton>
<p:confirmDialog global="true">
<p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
<p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
</p:confirmDialog>
</h:panelgGroup/>
</h:form>
Bean code:
#ManagedBean(name="bean")
#ViewScoped
public class Bean implements Serializable {
private SomeClass object;
#PostConstruct
public void init(){
this.object = new SomeClass();
}
public void calculate(){
//do some colculation (not related to amount field in object)
}
public void submit(){
//submit to database
}
//getter setter
}
When I enter a value in amount, lets say 50. and update the cal component I get the updated amount in the outputtext "50". However, in the confirm button message I get amount as 0 instead 50. How can I show the updated value in the confirm message?
PS:
Primefaces-4.0
Take a look at the user guide of primefaces in the confirm dialog section, in the Non-Global mode the document mentioned:
Message facet is
useful if you need to place custom content instead of simple text.
While in the Global mode, I can't find similar sentences like that, and I've tried using the facet in Global mode and it doesn't work.So,
Do you really use this confirm dialog multiple times?
If not:
I suggest you take away the global parameter and change your code like this:
<h:form>
<p:inputText value="#{bean.object.amount}"/>
<p:commandButton value="CALCULATE" update="cal" actionListener="#{bean.calculate()}"/>
<h:panelGroup id="cal">
<h:outputText value="#{bean.object.amount}"/>
<p:commandButton value="SUBMIT" actionListener="#{bean.submit()}" oncomplete="PF('confirmDlg').show()"/>
<p:confirmDialog header="Confirmation" widgetVar="confirmDlg">
<f:facet name="message">
<h:outputText value='Amount is : #{bean.object.amount} ?'/>
</f:facet>
<p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
<p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
</p:confirmDialog>
</h:panelGroup>
</h:form>
.
If so:
(You do use the confirm dialog multiple times and tired of writing several dialogs with same form but different message.)
I suggest you write a dialog on your own,and you can also change the message in the dialog from backing bean like what you did:
<h:form id="myForm">
<p:inputText value="#{bean.object.amount}"/>
<p:commandButton value="CALCULATE" update="cal" actionListener="#{bean.calculate()}"/>
<h:panelGroup id="cal">
<h:outputText value="#{bean.object.amount}"/>
<ui:param name="message" value="Amount is :#{bean.object.amount}?" />
<p:commandButton value="SUBMIT" actionListener="#{bean.setMessage(message)}" action="#{bean.submit()}" update="myForm:myDialog" oncomplete="PF('myDlg').show()"/>
</h:panelGroup>
<p:dialog id='myDialog' widgetVar="myDlg" header="Confirmation" modal="true" resizable="false">
<h:panelGrid columns="3">
<h:panelGroup styleClass="ui-icon ui-icon-alert" style="float:right"/>
<h:outputText value="#{bean.message}"/>
<h:outputText/>
<h:outputText/>
<p:commandButton value="Yes" type="button" icon="ui-icon-check" oncomplete="PF('myDlg').hide()"/>
<p:commandButton value="No" type="button" icon="ui-icon-close" onclick="PF('myDlg').hide()"/>
</h:panelGrid>
</p:dialog>
</h:form>
p:confirm does not implement state saving, thus it loses its attributes' values after the first JSF lifecycle. It also evaluates EL only once at view build time.
I posted the solution in this answer.

How to submit values in a pop-up panel?

I have bean struggling to understand how to use the rich:popupPanel component in the right way. There are (at least not that I could find) few post about how to use the rich:popupPanel and how to submit values from it.
To make matter worse the panel seams to add (when checking the html) a hard coded "_content" to its component id name (to the div generated). I have tried to use aj4:region tag to partial render the complete form. But that didn't seamed to work, cause nothing where posted to managed bean. So now I have one option left, where the panel has its own form, outside the main one on the page.
I can see that the evaluation of the form (popup) values is happening, but not the execution of the bean function that persist the values (I see the POST request of the command button). The only reason I can think of at the moment, is that the pop-up panel use another bean to persist the values that the main form on the page (both of them are session scoped).
I am thinking of omit the pop-up panel all together, since it seams so hard to make this work. Maybe its a well know secret, since it so few post about it. It behaves the same if if use componentController or only a a4j:commanLink.
How is it possible to submit values from a rich:popupPanel and invoke a backing bean function to persist the pop-up form values ?
Appreciate if someone can shed some light on this, greetings Chris.
I use Richfaces 4.0-final on Glassfish 3.1
<h:form id="main_form">
<!-- Command for popup -->
<a4j:commandLink actionListener="#{userController.prepareCreateSysRequest}" oncomplete="#{rich:component('popup_sys_user_req_form:popup_sys_user_req')}.show(); return false;"
execute="#this" value="Request New Sector/Category" />
...
<a4j:commandButton action="#{projectController.Create}" ...>
</h:form>
<h:form id="popup_sys_user_req_form">
<rich:popupPanel id="popup_sys_user_req" modal="true" autosized="true" resizeable="false">
<f:facet name="header">
<h:outputText value="New Project Request" />
</f:facet>
<f:facet name="controls">
<h:outputLink value="#"
onclick="#{rich:component('popup_sys_user_req')}.hide(); return false;">
X
</h:outputLink>
</f:facet>
<h:panelGrid columns="2">
<h:outputLabel value="Request New:" />
<h:selectOneMenu id="sys_req_type" value="#{userController.selectedSysRequestType}" required="true" requiredMessage="Request Type is required" title="Request Type">
<f:selectItems value="#{userController.getSysRequestTypeItems()}">
</f:selectItems>
</h:selectOneMenu>
<h:outputLabel value="Description:" />
<h:inputTextarea id="user_req_desc" value="#{userController.selectedSysUserRequest.description}" required="true" requiredMessage="Decription is missing" />
</h:panelGrid>
<a4j:commandButton action="#{userController.CreateSysUserRequest}" onclick="#{rich:component('popup_sys_user_req')}.hide(); return false;" execute="#form" render="popup_sys_user_req_form" value="Send Request" />
</rich:popupPanel>
</h:form>
For what I have done I used to have the issue to got to submit twice only the first time.
To fix it the form got to be outside the popupPane. And also that the popupPanel should have the attibute domElementAttachment="form".
Example.
<h:form>
<rich:popupPanel id="shipmentItemUpdateDialog"
autosized="true"
domElementAttachment="form">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="#{shipmentBundle.shipmentItemDetailsHeader}" />
</h:panelGroup>
</f:facet>
<f:facet name="controls">
<h:commandLink>
<h:graphicImage value="/core/images/modal/close.png"/>
<rich:componentControl target="shipmentItemUpdateDialog" operation="hide" />
</h:commandLink>
</f:facet>
<h:outputText for="shipmentItemName"
value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemName}"
/>
<h:inputText id="shipmentItemName"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.name}"
label="#{shipmentBundle.shipmentItemName}"
size="40" >
</h:inputText>
<h:outputText for="shipmentItemCode"
value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemCode}"
/>
<h:inputText id="shipmentItemCode"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.code}"
label="#{shipmentBundle.shipmentItemCode}"
size="40" >
</h:inputText>
<h:outputText value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemAmount}"
/>
<h:inputText id="shipmentItemAmount"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.amount}"
label="#{shipmentBundle.shipmentItemAmount}"
size="4" >
<f:validateLongRange minimum="1"/>
</h:inputText>
<h:outputText value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemNeedsCooling}"
/>
<h:selectBooleanCheckbox id="shipmentItemNeedsCooling"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.needsCooling}"
label="#{shipmentBundle.shipmentItemNeedsCooling}"
/>
<h:outputText for="shipmentItemDetails"
value="#{shipmentBundle.shipmentItemDetails}"
/>
<h:inputTextarea id="shipmentItemDetails"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.details}"
label="#{shipmentBundle.shipmentItemDetails}"
cols="38"
rows="5"
/>
</h:panelGrid>
<h:panelGrid columns="1" dir="LTR">
<h:panelGrid columns="2" dir="LTR">
<a4j:commandButton value="#{coreBundle.acceptButton}"
action="#{shipmentItemController.onUpdate()}"
render="shipmentItemsTable">
</a4j:commandButton>
<h:commandLink value="#{coreBundle.closeLink}"
immediate="true">
<rich:componentControl target="shipmentItemUpdateDialog" operation="hide" />
</h:commandLink>
</h:panelGrid>
<h:outputText value="#{coreBundle.requiredText}"/>
</h:panelGrid>
</rich:popupPanel>
</h:form>
I hope this helps.
I think you got it right.. think of the pop-up as a regular page. To submit and close the pop-up, do something like this:
<a4j:commandButton value="Save" onclick="#{rich:component('panelId}.hide();" render="..."/>
Hope this helps..

Resources