JSF Form with AJAX validation - Focus issues - ajax

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.

Related

Render hidden elements using JSF and AJAX

I've been facing some problems using JSF with AJAX to render a table without reloading the whole page every time I submit a form.
When I first run the server, my database is empty, so the page is supposed to show only a form to add books. When user submits the form, a fieldset whith all books is supposed to be rendered. I don't want this fieldset to be shown when database is empty.
This is a simple version of my code (it is just a small form and a table to be refreshed using AJAX):
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html 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:p="http://primefaces.org/ui">
<h:head />
<h:body>
<h:graphicImage library="img" name="caelum-logo.png"/>
<h:form>
<p>Book Title:</p>
<h:inputText id="title" value="#{livroBean.livro.titulo}" />
<h:commandButton value="Add book" action="#{livroBean.addFirstBook}">
<f:ajax execute="#form" render="title :addedBooksTable" />
</h:commandButton>
</h:form>
<div id="addedBooksTable">
<p:fieldset rendered="#{livroBean.numberOfBooks > 0}">
<h:dataTable value="#{livroBean.allBooks}" var="book">
<h:column>
<h:outputText value="#{book.titulo}" />
</h:column>
</h:dataTable>
</p:fieldset>
</div>
</h:body>
</html>
And i wanna focus on this part:
<h:commandButton value="Add book" action="#{livroBean.addFirstBook}">
<f:ajax execute="#form" render="title :addedBooksTable" />
</h:commandButton>
The fieldset and the table inside it are supposed to be hidden when there's no book added to the database, that's why i used <p:fieldset rendered="#{livroBean.numberOfBooks > 0}">. But I want it to be rendered after I click the commandButton, even if there's nothing at the inputText.
Here's what's happening when I test the code:
if I test the code just as it is with an empty database, the inputText is refreshed (it "erases" what were typed before the submisssion) when I click on the commandButton, but the fieldset is not. I know that the fieldset has a rendered="#{livroBean.numberOfBooks > 0}" and the inputText does not, but the method getNumberOfBooks is called everytime i click the commandButton, that's why I don't get it...
if I change the f:ajax tag so it ends up like this <f:ajax execute="#form" onevent="click" render="title :addedBooksTable" />, it solves the problem, but i can realize the screen flashing for a while when I click the commandButton. As far as I know, one of the uses of AJAX is that we don't want the screen flashing when a request is made.
Why is the fieldset rendered only when I use onevent="click"? Should I consider the flashing something normal? Is there a more elegant solution for that?
Thanks!
You can't ajax-update a plain HTML element. You can only ajax-update a JSF component. Simple reason is that the target must be resolveable by UIViewRoot#findComponent(), so that JSF can find it in the component tree and render the updated HTML into the Ajax response.
Replace
<div id="addedBooksTable">
by
<h:panelGroup layout="block" id="addedBooksTable">
Normally, this should have thrown an exception as described in How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar", but they removed this check in Mojarra 2.2.5 in order to support ajax-updating a specific iteration of <ui:repeat> and <h:dataTable> (this missing check will be fixed later on as that's indeed unhelpful to starters like you).
As to why adding onevent="click" appear to work, that's because it caused a JavaScript error which in turn caused the whole JavaScript/Ajax thing to break down, which in turn caused that the command button fall backs to default synchronous behavior with a full page reload (as if you aren't using <f:ajax> at all). You likely meant to use event="click" instead. The onevent attribute serves a different purpose. See also a.o. Proccess onclick function after ajax call <f:ajax>.

Trigger <a4j:ajax> request on page load

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.

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.

Although some validators in JSF are functioning well, some error messages or possibly some warnings appear on the console

In my web application in JSF, some validators such as a length validator <f:validateLength></f:validateLength>, a regular expression validator <f:validateRegex></f:validateRegex> and some other issue some error possibly a warning even if they are functioning well with no problem at all, when the JSF page is loaded.
The JSF ManagedBean is unnecessary here and the submit button presented in the following code has nothing to do with, since Ajax is fired on the valueChange event of the text field given.
Following is the simple JSF page code.
<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Demo</title>
</h:head>
<h:body>
<h:form>
<center><br/><br/><br/>
<h:inputText id="txtDemo" required="true" requiredMessage="Mandatory."
validatorMessage="The field should contain al least 10 digits">
<f:validateLength id="lenValidator" for="txtDemo" maximum="10"
minimum="2"/>
<f:validateRegex pattern="[0-9]*" for="txtDemo" id="txtPattern"/>
<f:ajax id="txtAjax" event="valueChange" execute="txtDemo msg"
render="txtDemo msg"/>
</h:inputText><br/>
<h:message id="msg" for="txtDemo" showDetail="true" style="color:red"/>
<br/>
<h:commandButton id="btnSubmit" value="Submit"/>
</center>
</h:form>
</h:body>
In the above code, although the validators <f:validateLength></f:validateLength> and <f:validateRegex></f:validateRegex> are functioning well, the length validator does not allow less than 2 and greater than 10 characters and the regular expression validator ensures that the field should contain only digits, red colored messages appear on the console, when this JSF page is load. The messages displayed are as follows.
SEVERE: /Restricted/TempTags.xhtml #12,93 id="lenValidator" Unhandled by MetaTagHandler for type javax.faces.validator.LengthValidator
SEVERE: /Restricted/TempTags.xhtml #13,82 id="txtPattern" Unhandled by MetaTagHandler for type javax.faces.validator.RegexValidator
Why are these messages displayed, event if they are functioning well with no problem?
It's just telling that the id attribute of those tags is not been handled. Indeed, those tags do not support an id attribute. Remove it.
<f:validateLength for="txtDemo" maximum="10" minimum="2"/>
<f:validateRegex for="txtDemo" pattern="[0-9]*" />
The for attribute is by the way unnecessary in this construct. You could also safely remove it. The for attribute applies only when targeting validators on inputs inside composite components.
See also:
JSF 2.1 tag documentation
<f:validateLength> tag documentation
<f:validataRegex> tag documentation
Unrelated to the concrete problem, the <center> element is deprecated since HTML 4.01 in 1998. Remove it as well. Use CSS margin: 0 auto on the containing block element with a fixed width instead.

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.

Resources