Trigger <a4j:ajax> request on page load - ajax

I have a page which has to trigger an AJAX request when it is loaded. I've managed to perform the request when clicking a button on the page. But I haven't managed to trigger this automatically on page load. The parameter to use comes from the other page via f:viewParam.
I've tried to use a load event which seems to be usable with f:ajax and HTMLGraphicImage or HTMLBody as per this thread but it doesn't work with a4j:ajax (or I may be missing something).
Tag Exception
<a4j:ajax> loadevent is not supported for the HtmlGraphicImage
I haven't posted the bean for simplicity as this part now works as I want to. My problem is about triggering the a4j:ajax tag. If you think the bean would be also needed just let me know.
I think there is a way to do it via PrimeFaces. I am not sure I'll be allowed to add this library to the project so please post other solutions if there are any.
Here is the JSF page. This one tries to use an image load event to trigger AJAX. There is also an attempt to use HTMLBody but it's tagged with ui:remove:
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:a4j="http://richfaces.org/a4j">
<ui:composition template="layouts/template.jsf">
<ui:define name="body">
<f:metadata>
<f:viewParam name="recordCode"
value="#{recordDetailBean.record.recordCode}" />
</f:metadata>
<h:graphicImage value="/images/transparent.gif">
<a4j:ajax event="load"
action="#{recordDetailBean.createDummyDelay}"
status="loadingRecordDetail" render="recordDetail" />
</h:graphicImage>
<ui:remove>
<a4j:ajax event="load"
action="#{recordDetailBean.createDummyDelay}"
status="loadingRecordDetail" render="recordDetail" />
</ui:remove>
<rich:popupPanel id="loadRecord" style="text-align:center"
autosized="true" modal="true" width="200">
<h:graphicImage value="/images/ajax-loader.gif" />
<br />
<h:outputText value="#{msg.loadingRecord}" />
</rich:popupPanel>
<a4j:status name="loadingRecordDetail">
<f:facet name="start">
<rich:componentControl event="start" operation="show"
target="loadRecord" />
</f:facet>
<f:facet name="stop">
<rich:componentControl event="stop" operation="hide"
target="loadRecord" />
</f:facet>
</a4j:status>
<h:form>
<a4j:commandButton value="Do something"
action="#{recordDetailBean.createDummyDelay}"
status="loadingRecordDetail" render="recordDetail" />
<a4j:outputPanel id="recordDetail">
<h:outputText value="#{recordDetailBean.dummyDelay}" />
</a4j:outputPanel>
</h:form>
</ui:define>
</ui:composition>
</html>
Thanks in advance.

Watching again my question I guess I should have asked that I wanted to link two pages passing a parameter and invoking a method of the managed bean being invoked prior to page render.
This is the approach I finally used. It is probably shown in other threads so this may be closed as duplicate. I also followed guidelines shown in this answer by BalusC regarding f:metadata. Unfortunately I couldn't make a "loading" h:popupPanel appear prior to change to the other page. If somebody could provide an approach to do this I would open another question:
Link on the first page:
<h:link value="#{rSearch.recordCode}" outcome="recordDetail">
<f:param name="recordCode" value="#{rSearch.recordCode}" />
</h:link>
Metadata on the page being called:
<ui:define name="metadata">
<f:metadata>
<f:viewParam name="recordCode" value="#{RecordDetailBean.theRecord.recordCode}" />
<f:event type="preRenderView" listener="#{RecordDetailBean.populateRecord}" />
</f:metadata>
</ui:define>
In the populateRecord method I use a DAO and the parameter stored in RecordDetailBean.theRecord.recordCode to retrieve all the info I need before the page is rendered.

Related

Richfaces 4 select only gets rendered correctly after a site refresh

I don't know if I'm doing something wrong or if it might be a bug or something.
My setup contains IntelliJ IDEA 12, JBoss AS 7.2.0.Final, Richfaces 4.3.4 within a war-File within an ear-Project (no Maven).
I have this index-page:
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich">
<rich:notifyMessage stayTime="3500" showShadow="true" showCloseButton="true" />
<f:view>
<h:head> <title> title </title> </h:head>
<h:body>
<!-- some more divs for page-design, but commented out at the moment -->
<div id="page">
<div id="index_workspace" style="width:1000px;margin:auto;">
<h:panelGrid columns="2" id="index_workspace_table">
<rich:panel id="index_workspace_navi_left" style="width:180px;min-height:600px;max-height:600px;">
<ui:include src="general/navi_left.xhtml"/>
</rich:panel>
<rich:panel id="index_workspace_content" style="width:550px; min-height:600px; max-height:600px;" rendered="#{not empty naviBean.content}">
<a4j:outputPanel id="index_workspace_content_ajax" ajaxRendered="true">
<ui:include src="#{naviBean.content}" id="current_site" />
</a4j:outputPanel>
</rich:panel>
</h:panelGrid>
</div>
<!-- some more divs for page-design, but commented out at the moment -->
</div>
</h:body>
</f:view>
</ui:composition>
Within the section I load the pages with forms and all the other cool stuff RF brings. But I have a rendering problem with this part of a loaded page:
<rich:select id="someID_1" rendered="true" immediate="true" required="true" enableManualInput="true" defaultLabel="someLabel">
<a4j:ajax render="true">
<f:selectItems id="selectlist" value="#{BackingBean.SelectableItem-ListGetter}"/>
</a4j:ajax>
</rich:select>
And here my problem is located:
This drop-down list only gets rendered on a page reload, e.g. F5 or CTRL-R action.
Also I could observe that if I set this element on some Kind of a "start page" (initially loaded on the index.xhtml) it gets rendered very well. In this case every other page containing this kind of element renders it correctly also.
I tried
updating JSF from 2.1 to 2.2.1 - that only brought up more problems - so I rolled it back.
The "standard" h:selectOneMenu behaves the same.
additional options within rich:select (e.g.: rendered, immediate, required, ...)
different ajax commands within the navigation (server, client, ajax, on different levels)
googling around since days - found no useable hint
I would appreciate every hint that guides me into the right direction as I feel confident, that I make some mistake I can't figure out...
Additionally my navigation looks like this (in another div on the index.xhtml):
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich">
<h:form id="navi_left">
<rich:panel>
<rich:panelMenu itemMode="ajax" groupMode="ajax" itemChangeListener="#{naviBean.updateContent}" >
<rich:panelMenuGroup itemLeftIcon="disc" label="Erfassung" name="#{naviBean.content}">
<rich:panelMenuItem label="someLabel_navi" name="path/to/page-not-getting-rendered-well.xhtml"/>
</rich:panelMenuGroup>
</rich:panel>
</h:form>
</ui:component>
Hope this helps helping me.
<a4j:ajax render="true">
<f:selectItems id="selectlist" value="#{BackingBean.SelectableItem-ListGetter}"/>
</a4j:ajax>
The above construct is not legal(as you've already seen yourself). The render attribute in there is not used for what you'd expect: to conditionally render the component; Rather, it's supposed to contain a list of on-page components to update via ajax.
To achieve the output I presume you're trying to get, you should use the following instead:
<a4j:region>
<rich:select id="someID_1" rendered="true" immediate="true" required="true" enableManualInput="true" defaultLabel="someLabel">
<f:selectItems id="selectlist" value="#{BackingBean.SelectableItem-ListGetter}"/>
</rich:select>
<a4j:region>
I think I found the problem. As my navigation and my desired site with the not correctly rendered component lie nested in <div>s on the third participating site - my index.xhtml - it seems to be impossible to let a jsf-component be rendered without having all (i.e. the navigation and the desired) sites processed on the server. So the following code-snippets work for my situation:
index.xhtml snippet:
<rich:panel id="index_workspace_content" style="width:550px; min-height:600px; max-height:600px;" rendered="#{not empty naviBean.content}">
<ui:include src="#{naviBean.content}" id="current_site" />
</rich:panel>
navi_left.xhtml snippet:
<h:form id="navi_left">
<rich:panel>
<rich:panelMenu itemMode="server" groupMode="client" itemChangeListener="#{naviBean.updateContent}">
<rich:panelMenuGroup label="someLabel" name="#{naviBean.content}">
<rich:panelMenuItem label="anotherLabel" name="path/to/page-being-rendered-correctly.xhtml"/>
</rich:panelMenuGroup>
...
</h:form>
component snippet in the desired.xhtml:
<rich:select id="someId" rendered="true" immediate="true" required="true" enableManualInput="true">
<f:selectItems var="#{backingBean.selectableItemList}" id="selectlist" value="#{backingBean.predefinedItem}"/>
</rich:select>
So what I have changed is the itemMode to "server", both of the others (ajax and client) will not work!
Setting the groupMode to "client" does not affect the renderprocess of desired.xhtml as it only describes the way the rich:panelMenu behaves.
What makes me feel a bit confused is, that the URL now gets extended with a "/index.xhtml". Before the change it was always just the url:port/context (e.g. localhost:8080/app ).
So it works now, but maybe it's not really what I wanted. I'll observe and report future facts concerning this itemMode-option here.

JSF Form with AJAX validation - Focus issues

Hi JSF experts out there ...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:o="http://omnifaces.org/ui">
<h:head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
</h:head>
<h:body>
<h:form>
<o:validateOneOrMore components="one two three" id="validate"/>
<p:message for="validate"/>
<p:inputText id="one" value="#{testBean.valueOne}">
<p:ajax event="change" process="#this" update="#form"/>
</p:inputText>
<p:inputText id="two" value="#{testBean.valueTwo}">
<p:ajax event="change" process="#this" update="two"/>
</p:inputText>
<p:inputText id="three" value="#{testBean.valueThree}">
<p:ajax event="change" process="#this" update="one two validate"/>
</p:inputText>
<p:commandButton process="#form"
update="#form"
value="Submit"
partialSubmit="true"
action="#{testBean.submit}"/>
</h:form>
</h:body>
</html>
a simple form with requirement of at least one form filled, immediate error reset and tab-able.
But i didn't get it work, tried different things as you can see in sample code.
What happens
hit submit -> error message shown: fine
enter entry in field one and leave with tab: fine (all fields are not in error state anymore and message is gone) BUT focus lost after complete AJAX update. Ok expected behavior of JSF and browsers as i read here, but how to solve?
delete all entries, hit enter -> input in field three and leave the field ... nothing changes ... even message is not gone sth. i also do not understand, since i updated all fields
Is there any solution out, for having a form like that ... where after each input validation of form will happen (meaning remove such global errors) and still have it quickly usable by using the tab-key?
thx.
This is a very annoying issue, which has to do with the way JSF preforms partial renders, there is an in depth post regarding JSF 2 AJAX focus issues.
Which offers a potential solution in the form of using the JSF JavaScript API to listen for triggered AJAX request and refocusing, have a look at the post for further details.

partial page rendering (PPR) with faces-redirect

I'm using PrimeFaces 3.5 and I faced a problem with partial page rendering. I need to load content from a Facelet file into "dynamic" part of a template.
index.xhtml:
<f:view>
<h:form id="form1">
<p:outputPanel layout="block">
<p:commandButton action="content-2?faces-redirect=false" update="display" />
</p:outputPanel>
<p:outputPanel id="display" layout="block">
content 1
</p:outputPanel>
</h:form>
</f:view>
content-2.xhtml:
<h:body>
content 2 loaded
</h:body>
When I click on the <p:commandButton>, then content-2.xhtml will be opened. However, this refreshes the whole page. The XML response contains like this:
<partial-response><changes><update id="javax.faces.ViewRoot">
When I change the action attribute to a method expression:
<f:view>
<h:form id="form1">
<p:outputPanel layout="block">
<p:commandButton action="#{myBean.increment}" update="display" />
</p:outputPanel>
<p:outputPanel id="display" layout="block">
#{myBean.count}
</p:outputPanel>
</h:form>
</f:view>
Then the display block updates as expected. The XML response contains like this:
<partial-response><changes><update id="form:display">
Why does the action="content-2?faces-redirect=false" way update the entire page?
I also tried to <ui:composition>, but in this case this reloads "static" part of template. I do not want it.
This is fully normal and expected behavior if you navigate to a different view by supplying a non-null outcome in the action attribute. JSF will then overrule the partial render with a render of #all. JSF/Facelets won't somehow automagically retain the common components in the tree as you seemed to expect. If you intend to dynamically change the component tree during a partial page rendering, then you need inside the <p:outputPanel id="display" layout="block"> either a dynamic include something like this (section is just an integer)
<ui:include src="section#{bean.section}.xhtml" />
or multiple conditionally rendered sections
<ui:fragment rendered="#{bean.section == 1}"><ui:include src="section1.xhtml" /></ui:fragment>
<ui:fragment rendered="#{bean.section == 2}"><ui:include src="section2.xhtml" /></ui:fragment>
<ui:fragment rendered="#{bean.section == 3}"><ui:include src="section3.xhtml" /></ui:fragment>
<ui:fragment rendered="#{bean.section == 4}"><ui:include src="section4.xhtml" /></ui:fragment>
Each has its own pros and cons depending on whether the include file contains form/input/command components and/or references view scoped beans. The <ui:include> runs namely during view build time like JSTL. See for more detail also JSTL in JSF2 Facelets... makes sense?
The presence of faces-redirect=false is not significant as it's the default already. If it were true, then a JavaScript window.location would be invoked on the target URL.

JSF form post with AJAX

I want the following form to use AJAX. So the comments are shown after clicking the command button and without reloading the page. What needs to be changed, using Java Server Faces 2.0?
Functionality: This form provides an inputText to define a topic. After pressing the commandButton, it is searched for comments regarding this topic. Comments are shown in a dataTable, if there are any. Otherwise Empty is shown.
<h:form id="myForm">
<h:outputLabel value="Topic:" for="topic" />
<h:inputText id="topic" value="#{commentManager.topic}" />
<h:commandButton value="read" action="#{commentManager.findByTopic}" />
<h:panelGroup rendered="#{empty commentManager.comments}">
<h:outputText value="Empty" />
</h:panelGroup>
<h:dataTable
id="comments"
value="#{commentManager.comments}"
var="comment"
rendered="#{not empty commentManager.comments}"
>
<h:column>
<h:outputText value="#{comment.content}"/>
</h:column>
</h:dataTable>
</h:form>
You need to tell the command button to use Ajax instead. It's as simple as nesting a <f:ajax> tag inside it. You need to instruct it to submit the whole form by execute="#form" and to render the element with ID comments by render="comments".
<h:commandButton value="read" action="#{commentManager.findByTopic}">
<f:ajax execute="#form" render="comments" />
</h:commandButton>
Don't forget to ensure that you've a <h:head> instead of a <head> in the master template so that the necessary JSF ajax JavaScripts will be auto-included.
<h:head>
...
</h:head>
Also, the element with ID comments needs to be already rendered to the client side by JSF in order to be able to be updated (re-rendered) by JavaScript/Ajax again. So best is to put the <h:dataTable> in a <h:panelGroup> with that ID.
<h:panelGroup id="comments">
<h:dataTable rendered="#{not empty commentManager.comments}">
...
</h:dataTable>
</h:panelGroup>
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
You need to modify your button:
<h:commandButton value="read" action="#{commentManager.findByTopic}">
<f:ajax render="comments" />
</h:commandButton>
This means, when the button is clicked, the action is executed, and the dataTable will be rendered and updated. This only works if the backing bean is at least view-scoped.

JSF 2.0 and JSTL use of c:set tag to store some temporary data

I'm developing a web application with JSF 2.0 (mojarra) + primefaces. In the past I successfully used the [c:set] tag of jstl library to store some temporary data or output form other tags.
In my current case I want to use that again but it doesn't work properly and I have no idea why. In the follow example it works but particularly. Why does the case 2 not work properly?
<h:form id="userAdministration">
<p:messages id="messages" showDetail="true" />
<p:dataTable id="userTable" selectionMode="single" var="user" value="#{users}">
<p:column>
<f:facet name="header">
<h:outputText value="#{message.user_table_header_id_column}" />
</f:facet>
<h:outputText value="#{user.id}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="#{message.global_table_header_action_column}" />
</f:facet>
<p:commandButton type="push" onclick="#{user.loginname}DeleteConfirmation.show()" value="#{message.global_table_action_delete}" image="ui-icon-trash">
<f:setPropertyActionListener value="#{user}" target="#{userAdministrationController.selectedUser}" />
</p:commandButton>
<!-- 1. WORKS FINE, STORED VALUE IS "loginname" -->
<c:set var="deleteConfirmationMessage" value="#{user.loginname}"></c:set>
<!-- 2. VALUE IS "!!!" AND NOT "loginname !!!" -->
<c:set var="deleteConfirmationMessage2">
<h:outputText value="#{user.loginname}" />!!!
</c:set>
<!-- 3. WORKS FINE (OUTPUT "loginname") -->
<h:outputText value="#{user.loginname}" />
<p:confirmDialog message="#{deleteConfirmationMessage}" header="#{message.user_dialog_delete_confirmation_title}" severity="alert" widgetVar="#{user.loginname}DeleteConfirmation">
<p:commandButton value="#{message.user_dialog_delete_confirmation_no}" onclick="#{user.loginname}DeleteConfirmation.hide()" update="#form" type="button" />
</p:confirmDialog>
</p:column>
Why does the case 2 not work properly?
<!-- 2. VALUE IS "!!!" AND NOT "loginname !!!" -->
<c:set var="deleteConfirmationMessage2">
<h:outputText value="#{user.loginname}" />!!!
</c:set>
That's because taghandlers and UI components doesn't run at the same time. JSTL tags are taghandlers and they run during building the view (when the XHTML file is converted to JSF component tree). JSF <h:xxx> tags are UI components and they run during rendering the view (when the JSF component tree is converted/rendered to HTML code). See also JSTL in JSF2 Facelets... makes sense?
So, when the <c:set> runs, the <h:outputText> hasn't run at all.
But in this particular construct you actually don't need the <h:outputText> at all. Apart from setting it as value of <c:set>, you could also just inline the EL expression raw in the template text (note that this works when using JSF with Facelets, not when using JSF with JSP; given the fact that you're using PrimeFaces, you're definitely using Facelets as PrimeFaces doesn't have a JSP taglib at all).
<c:set var="deleteConfirmationMessage2">
#{user.loginname}!!!
</c:set>
or perhaps you weren't aware that you can mix EL and plain strings in an attribute like
<c:set var="deleteConfirmationMessage2" value="#{user.loginname}!!!" />
or
<p:confirmDialog message="#{user.loginname}!!!">
Depending on the concrete functional requirement, which isn't exactly clear from the question, a different alternative may be to use the <o:cache> component of OmniFaces. This may be more useful if you intend to cache the value for a broader scope than just the page/request scope like as in your <c:set> examples.
Just making an educated guess, because I haven't tried to combine JSF and JSTL, but I believe the c:set would be handled before the h:outputText is rendered, so it would only see the static text in its body. I'm not sure what order tag handlers are called in relation to the JSF lifecycle but putting in some logging would clear that up.
xmlns:c="http://java.sun.com/jstl/core"
just add this as taglib for jstl

Resources