PrimeFaces dialog refer to parent - jsf

I have an xhtml page that display a Datatable with entries. I also have a button to insert a new entry, that displays a dialog that has a form. The insertion form is used as <ui:include> in the parent .xhtml as follows:
Parent file
<h:form id="mainForm">
<p:commandButton process="#form" update=":dlgGrp" oncomplete="dlg.show()"/>
<p:datatable id = "datatable">
various columns
.....
.....
</p:datatable>
</h:form>
<p:dialog widgetVar="dlg" >
<h:panelGroup id="dlgGrp">
<ui:include src="include.xhtml" />
</h:panelGroup>
</p:dialog>
</ui:composition>
Dialog file
<ui:composition xmlns . . .>
<h:form id="subForm">
various input fields
......
......
<p:commandButton process="#form" update=":mainForm" oncomplete="dlg.hide()"/>
</h:form>
</ui:composition>
How can I refer generically to a parent component as show in the file. In a few words as soon as I hit the submit button in the dialog, I want to update the main form and hide the dialog. These components however are in the "parent field".
This should probably be done programatically through the backing bean, since I do not want to include parent-specific actions in the child .xhtml, since I may aslo want to use it as a standalone .xhtml.

If you want to update the mainForm through a method in the backingBean. Just modify
<p:commandButton process="#form" action="#{backingBean.method}" oncomplete="dlg.hide()"/>
and in your backingBean do the following (see Primefaces Showcase):
public void method() {
// do something
RequestContext context = RequestContext.getCurrentInstance();
context.update(":mainForm");
}
You just need to check, if your mainForm is already in another NamingContainer.
If so, you need to change the context.update(...) accordingly.
Furthermore, if you want to update the mainForm from your backing bean, I would also recomment hiding the dialog in the backingBean, depending on the input processed. If e.g. some data is invalid, you don't want to hide the dialog. That cannot be done currently with your oncomplete action which is executed automatically after receiving the response from the server. The dialog would get close whether the input was correct or not.
So add to the method():
if (everythingWentFine) {
context.execute("dlg.hide();");
}
and remove the oncomplete from your p:commandButton.

Related

p:commandButton is reloading the page to open dialog

So I have this code:
<h:form id="serviceCustomFormForm">
<p:dialog id="parameterGroupAddDialog" widgetVar="parameterGroupAddDialog" header="#{messages.addParameterGroup}" modal="true" resizable="false">
<p:inputText value="#{serviceCustomFormBean.serviceParameterGroup.name}" styleClass="Wid90" />
<br />
<br />
<p:commandButton value="#{messages.save}" styleClass="Fright BlueButton" update="serviceCustomFormForm" actionListener="#{serviceCustomFormBean.addServiceParameterGroup}" oncomplete="PF('parameterGroupAddDialog').hide()" />
<p:commandButton value="#{messages.cancel}" styleClass="Fright RedButton" oncomplete="PF('parameterGroupAddDialog').hide()"/>
</p:dialog>
<div class="Container100">
<div class="ContainerIndent">
<p:commandButton value="#{messages.addParameterGroup}" icon="fa fa-plus-circle" styleClass="Fright CyanButton FloatNoneOnMobile" oncomplete="PF('parameterGroupAddDialog').show()" />
<div class="EmptyBox10 ShowOnMobile"></div>
</div>
</div>
</h:form>
When the page is first loaded the #PostConstruct method is called.
When I click the commandButton to open the dialog it's called again. And when I press the Cancel button inside the dialog it's called again.
This behavior does not occur in other parts of the application, and I can't see what I am missing here.
Update: As requested, the Bean code is here:
#ManagedBean
#ViewScoped
public final class ServiceCustomFormBean implements Serializable {
private ServiceParameterGroup serviceParameterGroup = new ServiceParameterGroup();
// Other attributes
#PostConstruct
private void init() {
// Reads attributes sent from previous page
}
public void addServiceParameterGroup() {
// Saves the serviceParameterGroup to database
}
// Getters and Setters
}
It's because the Commandbutton submits the form. You can
change to this:
<p:commandButton type="button" ...onclick="PF('parameterGroupAddDialog').hide()"
Type button tells primefaces not to submit the form. If the form isn't submitted oncomplete is never called. So it's onclick.
Try setting the following attributes to your 'Add Service' and 'Cancel' commandButton elements: partialSubmit="true" process="#this".
Code like this:
<commandButton value="#{messages.addParameterGroup}" ... partialSubmit="true" process="#this" ... />
By default, pf commandButtons try to submit the whole form, while in those two cases you just want to call the invoked method without doing a submit. With this, you are saying to primefaces that you don't want to submit it all (partialSubmit=true), and that you just want to process the invocation of the button itself (process=#this). Maybe that is your problem.
As an additional comment, i don't think getting the label values for the buttons from the bean is a good idea (unless you want to intentionally change the labels dynamically), because you will end up doing excessive requests to the bean. Better try using a messages properties file, as described in here http://www.mkyong.com/jsf2/jsf-2-0-and-resource-bundles-example/.
If I remember correctly, you should put your Dialog outside your main form, at the end of your body or use the appendTo="#(body)" param, and then, have another form inside the dialog.
After a long time dealing with this problem, I finally found the reason.
The annotation ViewScoped that I was importing in the backing bean was from the package javax.faces.view.
The correct one is javax.faces.bean.
Thanks for everyone that spend some time trying to help.

hiding and showing commandButton in jsf

I am new to JSF(PrimeFaces).
I have two commandButtons Do and Undo. I want only one button to be visible at one time.
like, When I click Do button, onclicking Do button should hide(performing its action simultaneously) and Undo button should be visible
and when i click Undo button onclicking it should hide and Do button should come back to active
I tried using
enable() and disable() methods but were of no use.
Can I get some help in achieving this. any predefined methods available?
Heard rendered attribute will help but couldnt understand what exactly will the attribute do .
Can someone explain pls
JSF rendered attribute will define if the component should be rendered/visible or not.
If
<h:commandButton value="Undo" rendered="#{false}" />
Then your above Undo button will be hidden.
rendered attribute can be bound to a ManagedBean property. In case if you want this dynamic, you have to update the component to see the result.
Here is a Small Example:
XHTML:
<h:panelGroup id="doBtnPG">
<h:commandButton value="Do" rendered="#{myBean.showDo}" action="#{myBean.doAction}">
<f:ajax render="unDoBtnPG"/>
</h:commandButton>
</h:panelGroup>
<h:panelGroup id="unDoBtnPG">
<h:commandButton value="Un Do" rendered="#{myBean.showUndo}" action="#{myBean.undoAction}">
<f:ajax render="doBtnPG"/>
</h:commandButton>
</h:panelGroup>
ManagedBean:
#ManagedBean
#ViewScoped
public class MyBean{
private boolean showDo=true;
private boolean showUndo=true;
public void doAction(){
showUndo=false;
}
public void undoAction(){
showDo=false;
}
//SETTER and GETTERS
}
In the above example, on clicking on one button the corresponding action method makes the property on which other button is being rendered as false, f:ajax will re render/update the other button's panelGroup to reflect the changes.
Since you marked this question as Primefaces, here is the XHTML code for Primefaces:
<h:panelGroup id="doBtnPG">
<p:commandButton value="Do" rendered="#{myBean.showDo}"
action="#{myBean.doAction}" update="unDoBtnPG"/>
</h:panelGroup>
<h:panelGroup id="unDoBtnPG">
<p:commandButton value="Un Do" rendered="#{myBean.showUndo}"
action="#{myBean.undoAction}" update="doBtnPG"/>
</h:panelGroup>
Notice that on Primefaces commandButtons you dont need to use f:ajax or p:ajax explicitly because they are Ajax by default.
Please note that the functions enable() and disable() provided by Primefaces are only client side. When disabled attribute is false and if you enable the button using enable(), it will not fire your action method.

PrimeFaces dialog lazy loading (dynamic="true") does not work?

I have recently changed all my beans from RequestScoped to ViewScoped. Suddenly, the lazy loading of dialogs does not work. I am using PrimeFaces JSF library.
<html>
<h:body>
<f:view>
<h:form>
<p:commandButton id="addId" value="Add" title="Add" type="button" onclick="dlgMultiFileSelect.show();"/>
...
</h:form>
<p:dialog header="Dialog" widgetVar="dlgMultiFileSelect" modal="true" resizable="true" dynamic="true">
<ui:include src="/dialogs/media_browser.xhtml"/>
</p:dialog>
</f:view>
</h:body>
</html>
Seems like dynamic="true" does not work since the backing bean in media_browser.xhtml gets initialized immediately, and not when button is clicked.
Am I doing something wrong?
Using PrimeFaces 3.5.0.
have found some pretty easy workaround:
Let's quote BalusC's answer on this other question:
Skip executing <ui:include> when parent UI component is not rendered
The <ui:include> runs as being a taghandler during the view build time, while the rendered attribute is evaluated during the view render time.
Regarding his first proposal:
Use a view build time tag like <c:if> around the <ui:include> part.
So first add some new method to your bean. (may even be useful in some application scoped bean for reuse)
public boolean isAjaxRequest() {
boolean val = FacesContext.getCurrentInstance().getPartialViewContext().isAjaxRequest();
return val;
}
Then enclose your <ui:include> inside following <c:if>:
<p:dialog id="yourDlg" header="Dialog" widgetVar="dlgMultiFileSelect" modal="true" resizable="true" dynamic="true">
<c:if test="#{applicationBean.ajaxRequest}">
<ui:include src="/dialogs/media_browser.xhtml"/>
</c:if>
</p:dialog>
So at page load time, the request isn't ajax... and on other ajax requests on base page, the dialog won't be updated...
But if you trigger your dialog
<p:commandButton id="addId" value="Add" title="Add" type="button"
oncomplete="dlgMultiFileSelect.show();" update=":yourDlg"/>
and update it's content, it will finally be rendered!
Please note following changes: The p:dialog id, p:commandButton update and p:commandButton oncomplete
Facelet tag ui:include will get processed earlier in the cycle and hence it is getting initialized. If you want to update the content of the dialog on button click, you need to do so using the update="id of the dialog" on your commandButton. You can use for your ui:include so that the page is not loaded initially.

why JSF 2.0 "rendered" does not work without refreshing the page?

When I click a method to render a part of the page, it does not change anything until I manually refresh the page.
Here is the bean:
boolean showPage = true;
public boolean getShowPage(){
return showPage;
}
Here is the view:
<h:form>
<p:commandButton value="Click" action="#{bean.hideContents()}" />
</h:form>
<p:panel rendered="#{bean.showPage}">
Contents
</p:panel>
The panel gets hidden when I manually refresh the page, otherwise it does not.
How is this caused and how can I solve it?
You need to update a parent component of the conditionally rendered component. You can do that by specifying its client ID in the update attribute of the <p:commandButton>:
<h:form>
<p:commandButton value="Click" action="#{bean.hideContents}" update=":panel" />
</h:form>
<h:panelGroup id="panel">
<p:panel rendered="#{bean.showPage}">
Contents
</p:panel>
</h:panelGroup>
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?

PrimeFaces :: display p:Dialog to fill-in a form field, without reposting

I have a data-entry form that displays a number of fields (mostly p:inputText) for the user to provide. Some of these are LOVs so I display a p:dialog to allow the user to select the right value. The p:dialog is displayed by means of a p:commandLink next to the p:inputText. Main parts of code shown below:
<h:form id="parentForm">
(...)
<p:inputText value="#{CustomerCEVController.customer.municipality}" id="customerMncName"/>
<p:commandLink type="button" onclick="MunicipalityDlg.show()" styleClass="ui-icon ui-icon-search"/>
(...)
<p:commandButton value="Submit" id="save" actionListener="#{CustomerCEVController.saveButtonListener}" /> (...)
</h:form>
The problem is, whenever the user clicks on the p:commandLink to display the p:dialog (to allow him to select one of the values) the outer form goes through its lifecycle phases (restore view, apply request values, process validations, etc.) since the p:commandLink is placed inside an h:form. How can I implement this dialog-displaying functionality while avoiding posting the h:form with every dialog that the user opens?
Just add "return false" as the last statement to onclick event handler. It prevents commandLink's default function (posting the form).
Just add set the appendToBody attribute to true on <p:dialog>
<p:dialog header="Header Text" widgetVar="dlg" appendToBody="true">
//Content
</p:dialog>
This appends the dialog as a child of the document body outside the parent form.

Resources