How to customize the presentation of faces messages - validation

I would like to customize the presentation of faces messages.
For this,
<h:inputText id="name" required="true" />
when validation is failed, then it will be shown in a
<h:message for="name" />
However, I would like to customize the presentation call JS as follows:
<div class="notification"></div>
function showNotification(msg){
$(".notification").html(msg);
$(".notification").fadeIn(1000, function(){
timeout = setTimeout(function(){
$(".notification").fadeOut(1000);
}, 5000);
});
}
How can I achieve this?

You can use FacesContext#getMessageList() to get the messages in the view, if necessary the ones for a specific client ID. You can iterate over them in a ui:repeat. Each item is a FacesMessage which has several getters. You can display any HTML in the message unescaped by using <h:outputText escape="false">.
So, in a nutshell:
<ui:repeat value="#{facesContext.messageList('form:name')}" var="message">
<div><h:outputText value="#{message.summary}" escape="false" /></div>
</ui:repeat>
(in the above example, I assume that your form has id="form")
Or, if that HTML help link is actually not part of the message, then so:
<ui:repeat value="#{facesContext.messageList('form:name')}" var="message">
<div>#{message.summary} help</div>
</ui:repeat>

Related

How Can I Use Ajax To Update A GraphicImage Without Blinking?

Please have a look at the following form. In particular, take note of the ajax and graphicImage elements. The ajax element is embedded in a selectOneMenu. When the menu selection is changed the image is correspondingly updated. The update will sometimes cause a "blink" (old image disappears, form resizes (shrinks), new image appears, form is back to original size). I am guessing that the not blink (blink) results from the speed (or lack thereof) with which the new image is fetched from the url (a server elsewhere on the web). Short of caching all the images locally, is there a way to address this? Cause old image to remain in place until the new image is ready? At least prevent the form from resizing?
<h:form rendered="#{orderController.addingNew}" styleClass="demo">
<fieldset>
<legend>New Order</legend>
<h:panelGrid columns="2">
<h:outputText value="Patient"></h:outputText>
<h:selectOneMenu validatorMessage="required" value="#{orderController.patientId}" onchange="submit()">
<f:selectItems value="#{orderController.patients}" />
</h:selectOneMenu>
<h:outputText value="Product"></h:outputText>
<h:selectOneMenu value="#{orderController.productId}">
<f:selectItems value="#{orderController.products}" var="product" itemValue="#{product.id}" itemLabel="#{product.name}" />
<f:ajax render="productImage" listener="#{orderController.productSelectionChanged}"/>
</h:selectOneMenu>
<h:graphicImage url="#{orderController.productImageUrl}" id="productImage"/>
</h:panelGrid>
<h:panelGroup>
<h:commandButton value="Save" action="#{orderController.save}" accesskey="s" styleClass="demo"/>
<h:commandButton value="Cancel" action="#{orderController.cancel}" accesskey="c" immediate="true" styleClass="demo"/>
</h:panelGroup>
</fieldset>
<h:outputText value=" " />
</h:form>
You could bind an onevent attribute to your ajax tag:
<f:ajax render="productImage" listener="#{orderController.productSelectionChanged}"
onevent="ajaxEventListener"/>
Then, you get notified whenever some phase of the ajax process happens. You might be interested in implementing something like this with jQuery:
function ajaxEventListener(data) {
var status = data.status; // Can be "begin", "complete" or "success".
var source = data.source; // The parent HTML DOM element.
//Give your form an id in order to access the image in JS
var $image = $(document.getElementById("yourFormId:productImage")); //Grab your image
switch (status) {
case "begin": // Before the ajax request is sent.
// Fade out your image
$image.fadeOut( "slow" );
break;
case "success": // After update of HTML DOM based on ajax response.
// You've got the url properly updated, start fading in the image again
$image.fadeIn( "slow" );
break;
}
}
In order to improve loading times, you should read some papers about how to cache resources in the web browser. That's not JSF specific, though, it's something you could do with a web filter.
See also:
Execute JavaScript before and after the f:ajax listener is invoked
How to select JSF components using jQuery?
http://api.jquery.com/fadeout/
http://api.jquery.com/fadeIn/

jsf component.valid first time entering the page

I'm displaying a small icon next to input fields when validation did not pass. I can do it but I was hoping for a better solution than what I have currently:
<p:inputText ... binding="#{myfield}">
<f:validator binding="#{myfieldValidator}"/>
<f:ajax event="blur" render="myfieldFeedback"/>
</p:inputText>
<h:panelGroup id="myfieldFeedback">
<div class="failedIndicator colorRed" jsf:rendered="#{myFieldvalidator.isIndicatorvisible.myFieldfailed}">!</div>
<div class="successIndicator" jsf:rendered="#{myFieldValidator.isIndicatorVisible.myFieldSuccess}">v</div>
</h:panelGroup>
With inside my validator:
private Map<String, Boolean> isIndicatorVisible;
isIndicatorVisible.put("myFieldSuccess", false);//if validation succeeds goes to true
isIndicatorVisible.put("myFieldFailed", false);// opposite of above
I'm hoping for a better solution (that doesn't use a map) like this:
<h:panelGroup id="myfieldFeedback">
<div class="#{myfield.valid ? 'successIndicator' : 'noDisplay'}">v</div>
<div class="#{myfield.valid ? 'noDisplay' : 'failedIndicator colorRed'}">!</div>
</h:panelGroup>
The field is valid upon entenring for the first time the dialog in which the form is displayed. Thus there is a valid feedback which is displayed I do not wish to have.
You thus want to make sure the conditions are only evaluated during a postback request, not during an initial (GET) request. You can check that by FacesContext#isPostback().
<h:panelGroup id="myfieldFeedback">
<ui:fragment rendered="#{facesContext.postback}">
<div class="...">v</div>
<div class="...">!</div>
</ui:fragment>
</h:panelGroup>

JSF ajax render message and redirect

I have a JSF application where users login in a login form inserting their email and password. The ManagedBean has the following 2 methods.
The method checkIdentity1() returns an URL ("" if the validation is incorrect in order to stay in the same page, or /useraccount.xhtml if inserted data is ok in order to go to next page).
The method checkIdentity2() returns a boolean value (false if the validation is wrong in order to show a message, true if it is ok).
loginManagedBean.java
public String checkIdentity1()
{
String strResponse="";
//check id
if(email.equals("jose#a.com") && password.equals("1234"))
{
strResponse="/useraccount.xhtml?faces-redirect=true";
} else {
}
//
return strResponse;
}
public boolean checkIdentity2()
{
boolean bResponse=false;
//check id
if(email.equals("jose#a.com") && password.equals("1234"))
{
//setpassIncorrecta(false);
} else {
bResponse=true;
}
//
return bResponse;
}
What I am trying to do is to mix ajax and JSF to show "Email and/or password incorrect" when I click Login button and validation fails and go to account.xhtml when validation is ok. But when I insert incorrect email and password no message is displayed, and when I insert them correctly the page is no redirected to account.xhtml. What am I doing wrong?
This is my Facelet
<h:form>
<!--Email-->
<h:inputText id="email" label="email" required="true" size="32" maxlength="32"
value="#{loginManagedBean.email}"
requiredMessage="Insert your email">
</h:inputText>
<h:message for="email" />
<!--Password-->
<h:inputSecret id="password" label="password" required="true" size="32" maxlength="40"
value="#{loginManagedBean.password}"
requiredMessage="Insert your password">
</h:inputSecret>
<h:message for="password" />
<!--Button-->
<h:commandButton value="Login" action="#{loginManagedBean.checkIdentity1()}">
<f:ajax execute="#form" render=":loginErrorMessage" />
</h:commandButton>
</h:form>
<h:panelGroup id="loginErrorMessage">
<h:outputText value="Email and/or password incorrect" rendered="#{!loginManagedBean.checkIdentity2()}" />
</h:panelGroup>
Like I explained in the comment, that's just the way JSF works: if a request fails validation, the action method will not be executed. That's defined the JSF request processing lifecycle (which I won't get into here). For the purpose of this answer, all you need to know is that the validation of request parameters happens before the action methods are considered. That being said, if the validation fails, the request processing is short-circuited there and then. To achieve what you're looking for, you should consider the following:
To conditionally render that component, you can examine the validation status in your page:
<h:outputText value="Email and/or password incorrect" rendered="#{facesContext.validationFailed}" />
Ideally, you should just use the <h:messages/> component, where you don't need to manage message display yourself
JSF will stay on the same page by default, if the validation fails, so you needn't take any special steps to that effect

JSF input file tag + ajax

I lost whole day on this issue and got nothing. I know that the question was asked but it was never answered. BalusC said that this issue is fixed in JSF 2.2.5 but either it is not or i do something wrong.
I use h:inputFile tag with ajax to render choosen image in preview div after chosing one from disk. However it's rendered only once and i have to reload page to see next chosen image. It causes more errors. For example when I use SUBMIT button to send chosen image to DB, ajax from commandLink is not executed (image is saved and rendered after page after refresh).
It looks to me like ajax is broken after chosing an image from disk and followed ajax actions are not executed, even they dont belong to h:inputfile.
This is my JSF form (one of its versions because i tried so many tricks)
<h:panelGroup class="photo-update" rendered="#{profileBean.page eq 'photo'}">
Dodaj lub zmień swoje zdjęcie profilowe[...]
<h:form enctype="multipart/form-data">
<h:panelGroup id="form-content">
<h:panelGroup id="current-image" class="current-image">
<p:graphicImage value="#{imageBean.getUserImage()}"/>
</h:panelGroup>
<h:panelGroup id="accept-container-ajax">
<h:panelGroup id="accept-container" class="accept-container"
rendered="true">
<div class="arrow">
<img src="resources/images/arrow.png"/>
<div class="change-text">Zamień na</div>
</div>
<h:panelGroup id="new-image" class="new-image">
<p:graphicImage value="#{profileBean.getConvertedImage()}"/>
</h:panelGroup>
<h:commandLink class="btn btn-default ok-button" value="zatwierdź"
action="#{profileBean.uploadPhoto}">
<f:ajax render="accept-container-ajax current-image"
execute="#form"/>
</h:commandLink>
</h:panelGroup>
</h:panelGroup>
<div class="btn btn-default change-image-container">
Zmień zdjęcie
<h:inputFile immediate="true" id="change-image"
class="change-image" value="#{profileBean.image}">
<f:ajax render="accept-container-ajax" execute="#form"/>
</h:inputFile>
</div>
</h:panelGroup>
</h:form>
</h:panelGroup>
This is fragment of the bean:
public StreamedContent getConvertedImage() throws IOException {
return userBo.convertPartToStream(image);
}
public void uploadPhoto() {
this.renderChangeContainer = false;
if (userBo.addImage(this)) {
FacesContext.getCurrentInstance().addMessage(
null, new FacesMessage(
FacesMessage.SEVERITY_INFO, "...", null));
} else {
FacesContext.getCurrentInstance().addMessage(
null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "...", null));
}
}
injected BO methods are OK.
Please give me a clue what is going on.
EDIT:
I also see ugly iframe with some response content i guess.

JSF: Is there a way to create animation effect when insert a new record into table?

I've been googling this question a lot and I dont seem to find a solution. I wonder if any developer out there that able to achieve this? I know there are couple ajax framework out there for JSF like Richfaces, primefaces, icefaces ... I have look at their showcase, and could not seems to find what I am looking for.
This is how it would work for h:dataTable assuming that we always append to the table:
<h:form>
<h:panelGroup id="animatedTableGroup">
<h:dataTable id="animatedTable" value="#{myBean.rows}" var="row">
<h:column>
<h:outputText value="#{row}"/>
</h:column>
</h:dataTable>
<rich:jQuery timing="onload"
selector="#animatedTable tr:last" query="fadeOut('slow')"/>
<rich:jQuery timing="onload"
selector="#animatedTable tr:last" query="fadeIn('slow')"/>
</h:panelGroup>
<a4j:commandButton value="Add row"
action="#{myBean.addRow}" reRender="animatedTableGroup"/>
</h:form>
And the bean:
public void addRow() {
rows.add(new Date().toString());
}
public List<String> getRows() {
return rows;
}
If you want to insert into selected position in the table, then it's better to use rich:extendedDataTable and use something like this as selector:
<rich:jQuery timing="onload"
selector="#animatedTable tr.rich-sdt-row-selected" query="..."/>
Richfaces has native support for jQuery using rich:jQuery component. You can use any effects that jQuery supports. For example:
<h:commandButton id="submitButton" value="Submit"
action="#{myBean.myAction}" style="display: none;"/>
<rich:jQuery selector="#submitButton"
query="fadeIn('slow')" timing="onload">
or
<h:commandButton id="submitButton" value="Submit"
action="#{myBean.myAction}"
onmouseover="jQuery(this).fadeOut('slow');"
onmouseout="jQuery(this).fadeIn('slow')"/>
You can find more examples here: http://docs.jboss.org/richfaces/latest_3_3_X/en/devguide/html/rich_jQuery.html

Resources