p:commandbutton action doesn't work inside p:dialog - jsf

I have a p:dialog and there is a panel inside it. The problem is "Save" button's action method is not working. It doesn't even calls the method. I can reach the method def. with ctrl+lm so there is no problem with method name.
<h:body>
<h:form id="createAppUserForm" prependId="false">
....
<p:dialog id="newRoleDialogId"
header="Add New Role"
resizable="true"
draggable="true"
widgetVar="newRoleDetailsDialog"
appendToBody="true"
>
<p:panel id="newRoleDialogPanel">
<p:panelGrid id="newRoleDialogPanelGrid" columns="2" style="width: 100%" styleClass="panelGridWithoutBorder">
<h:outputText value="Role Name :"/>
<p:inputText value="#{createAppUserController.selectedRole.name}"/>
<h:outputText value="Role Desc :"/>
<p:inputText value="#{createAppUserController.selectedRole.description}"/>
</p:panelGrid>
<center>
<p:commandButton value="Save"
update="roleListDataTable newRoleDialogPanelGrid growlCreateAppUser"
oncomplete="if (!args.validationFailed) newRoleDetailsDialog.hide()"
action="#{createAppUserController.saveNewRole()}"/>
<p:commandButton value="Cancel"
immediate="true"
onclick="newRoleDetailsDialog.hide()" />
</center>
</p:panel>
</p:dialog>
</h:form>
</h:body>

The dialog, when used with an appendToBody/appendTo="#Body" must have its own form.
<p:dialog>
<h:form>
...
</h:form>
</p:dialog>
Because, when the dialog is generated into HTML output, it's by JavaScript relocated to the end of HTML <body> which causes it to not be sitting in any form anymore. The generated HTML DOM tree ends up to look like this (use webbrowser's dev tools to see it):
<body>
...
<form id="createAppUserForm">
...
</form>
...
<div id="newRoleDialogId" class="ui-dialog ...">
...
</div>
</body>
The appendToBody="true" plays a role in here. The end of body ensures easy and best cross browser compatibility of displaying a modal dialog by JavaScript.
The same is true by the way for a p:overlayPanel with an appendTo...
But also make sure there is, before 'moving' the p:dialog, there is not a nested h:form. So prevent
<h:form>
...
<p:dialog>
<h:form>
...
</h:form>
</p:dialog>
...
</h:form>
Since although it ends up like
<body>
...
<form id="createAppUserForm">
...
</form>
...
<div id="newRoleDialogId" class="ui-dialog ...">
<form>
...
</form>
</div>
</body>
it is initially invalid html
See also:
How to show details of current row from p:dataTable in a p:dialog and update after save
Creating master-detail table and dialog, how to reuse same dialog for create and edit
How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?

Adding (process="#this") to commandButton worked for me.

try this p:remoteCommand
http://www.primefaces.org/showcase/ui/ajax/remoteCommand.xhtml
this is my example
<h:commandButton value="Aceptar" type="button" onclick="irAConf()" class="art-button">
</h:commandButton>
<p:remoteCommand name="irAConf"
action="#{configuracionBean.irAConfiguracion}"/>

The appendToBody="true" plays a role in here. This attribute have been removed from in latest version. Please look for other alternative

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"/>

a4j Render not working

I have a modal panel similar to the one below in the xhtml page.
<h:form>
<a4j:commandLink action="" rerender="panel1">
</h:form>
<a4j:outputPanel id="panel1">
<rich:modalpanel>
<a4j:form>
<h:panelgroup binding=#{mybean.panel}/>
<a4j:commandButton id="save">
</a4j:form>
</rich:modalpanel>
</a4j:outputPanel>
When I click on the a4j command link,want to display the modal panel with differrent values. It works correctly if there is no a4j:form inside the modal panel. But I want to validate and save the attributes inside the modal panel on click of save button, and hence couldnt proceed with out the form component. But strangely when I add the a4j:form, panel group stop re rendering values. Please help me to sove this.
I also tried to place both inside same form, but then it worked in a very irregular manner.
Maybe try it this way:
<h:form>
<a4j:commandLink action="" rerender="panel1">
</h:form>
<rich:modalpanel>
<h:form>
<a4j:outputPanel id="panel1">
<h:panelgroup binding=#{mybean.panel}/>
<a4j:commandButton id="save">
</a4j:outputPanel>
</h:form>
</rich:modalpanel>
Works for me with Popuppanel

JSF 2 AJAX - reload whole div (e.g. <ui:include src="toReloadData.xhtml" />)

I'm working with jsf2 and want to use the ajax-functionality of it. Problem: I've already seen some ajax refresh things. But nothing to refresh a whole div...
I have a xhtml page with data from my bean, and i don't really want to refresh all fields of it, it would be easier to refresh the whole ui:include...
does anybody knows a solution? Or do I have to refresh all fields manually?
best regards
Just put them in some container component with an ID and use it in render attribute of f:ajax.
<h:form>
<h:commandButton value="submit" action="#{bean.submit}">
<f:ajax render=":foo" />
</h:commandButton>
</h:form>
<h:panelGroup id="foo" layout="block">
<ui:include src="include.xhtml" />
</h:panelGroup>
Note that <h:panelGroup layout="block"> renders a <div>. If you omit the layout attribute, it defaults to <span> (only whenever there are any attributes which needs to be rendered to HTML, like id).
Okay BalusC, but I'm still having a problem with the includes and ajax.
my index.xhtml includes a search.xhtml and a results.xhtml
the ajax-part is in search.xhtml and the toRender-id is in results.xhtml...
so at rendering the jsf-tags there's the problem that there's no toRender-Id at this time...
EDIT:
Okay the problem was not the arrangement of the includes, it was that the ajax-parts must be in the same form tag like this:
<h:form>
<div id="search" class="search">
<ui:insert name="search" >
<ui:include src="search.xhtml" />
</ui:insert>
</div>
<h:panelGroup id="ajaxResult" layout="block">
<ui:insert name="searchResults" >
<ui:include src="searchResults.xhtml" />
</ui:insert>
</h:panelGroup>
</h:form>
search contains f:ajax tag, ajaxResult is toRenderId
best regards, emre

Resources