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

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

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

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

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

Jsf 2.0-<ui:include>xhtml included always even if rendered is false

I have a home page xhtml where i am including 3 child xhtml based on conditions.
The issue i am facing is , whatever be the scenario,Book.xhtml always gets invoked.
I changed the rendered condition to false or move out to another condition, but the file always gets invoked Due to which its backing bean also is invoked causing unwanted overhead.
Please provide me a solution
<ui:composition template="/xhtml/baseLayout.xhtml">
<ui:define name="browserTitle">
<h:outputText value="HOME PAGE" />
</ui:define>
<ui:define name="header">
<ui:include src="/xhtml/header.xhtml" />
</ui:define>
<ui:define name="bodyContent">
<h:panelGrid width="100%"
rendered="#{pogcore:isRoleAuthorized(BUNDLE.SUPER)}" >
<ui:include src="/xhtml/SuperUser.xhtml" />
</h:panelGrid>
<h:panelGrid width="100%"
rendered="#{pogcore:isRoleAuthorized(BUNDLE.MAINTENANCE)}" >
<ui:include src="/xhtml/Maintenance.xhtml" />
</h:panelGrid>
<h:panelGrid width="100%"
rendered="#{pogcore:isRoleAuthorized(BUNDLE.PRINT)}">
<ui:include src="/xhtml/Book.xhtml" />
</h:panelGrid>
</ui:define>
</ui:composition>
This is happening due to lifecycle of jsf. JSF UIComponents are evaluated during view render time where as jstl tags are evaluated at build time.
So when you use rendered attribute of h:panelGrid it is too late to not invoke managed beans under the included page. To resolve this try having conditions using jstl tag, the following should work for you.
<c:if test="#{bean.yourCondition}">
<h:panelGrid width="100%">
<h:outputText value="#{bean.yourCondition}"/> <!--if this is not getting printed there is smtg wrong with your condition, ensure the syntax, the method signature is correct-->
<ui:include src="/xhtml/Book.xhtml" />
</h:panelGrid>
</c:if>
<c:if test="#{!bean.yourCondition}">
<h:outputText value="#{bean.yourCondition}"/> <!--This should print false-->
</c:if>
The document below describes the details of jstl and jsf lifecycle.
http://www.znetdevelopment.com/blogs/2008/10/18/jstl-with-jsffacelets/
Check the following document to see another way to solve this without using jstl tags.
http://pilhuhn.blogspot.com/2009/12/facelets-uiinclude-considered-powerful.html
Do this:
Always include the sub pages
Put the panelGrid (with the rendered) inside the page that you always include
Why ? Because the inclusion is performed before the rendered is evaluated.

Why doesn't h:commandButton execute the action method when combined with c:chose?

I've seen a strange problem in my project. It's that <h:commandButton/> does not execute the action method.
<c:choose>
<c:when test="#{empty param.t}">
// HTML
</c:when>
<c:when test="#{param.t eq 'normal'}">
// HTML
<h:form>
<h:commandButton value="ADD" action="#{addBean.doSomething}" />
</h:form>
<c:when>
</c:choose>
When I move <h:form> into first c:when, then the action method is called. Otherwise, it isn't. Why?
I'll ignore the syntax error in your EL (a missing }).
The command button won't be executed when #{param.t eq 'normal'} evaluates to false at the point the form submit request is to be processed. You need to maintain the same parameter for the subsequent request so that the button will be rendered so that JSF can confirm that the enduser is allowed to invoke the action. You can do this by adding a <f:param>:
<h:form>
<h:commandButton value="ADD" action="#{addBean.doSomething}">
<f:param name="t" value="#{param.t}" />
</h:commandButton>
</h:form>
Note that this is supported since JSF 2.0 only. On JSF 1.x you'd need to replace h:commandButton by a h:commandLink if you want f:param support.
Unrelated to the concrete problem, you should try to avoid JSTL as much as possible in your JSF views. If the intent is to render view parts conditionally (not to build view parts conditionally), then you should rather be using the JSF component's rendered attribute instead of a JSTL <c:choose> or <c:if>:
<h:panelGroup rendered="#{empty param.t}">
// HTML
</h:panelGroup>
<h:panelGroup rendered="#{param.t eq 'normal'}">
// HTML
<h:form>
<h:commandButton value="ADD" action="#{addBean.doSomething}" />
</h:form>
</h:panelGroup>

Resources