I would like to validate every field in my form when each field lose the focus, when this happens i would like these actions happen:
1) in the right side of the field appears an image, a .gif (to represent that the system is checking the user input)
2) when finished appears another .gif (which depends of the input, 'sucess.gif' or 'error.gif', for example) and a message on the right side.
I don't want to use popup or something like, the user is gonna lose usability and i don't want this.
I'm trying to do something like this, this is what i have done so far:
<h:form id="form">
<h:panelGrid columns="3" >
<h:outputLabel for="first_name" value="First Name:" />
<h:inputText id="first_name" value="#{register.bean.firstName}" >
<f:ajax event="blur" render="m_first_name" />
</h:inputText>
<a4j:status name="ajaxStatus">
<f:facet name="start">
<h:graphicImage name="loader.gif" library="images" />
<h:outputText value="Processing ..." />
</f:facet>
</a4j:status>
<a4j:commandButton value="Register !" action="#{register.validateName}" status="ajaxStatus" />
</h:panelGrid>
</h:form>
I was searching for some solution on Google and I think
<a:a4j ... >
is my best option, because of the onbegin
and oncomplete
attributes.
There's some attribute as these in some native tag in JSF 2 ?
UPDATE: @BalusC approach:
<!DOCTYPE html>
<html lang="pt-br"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Insert title here</title>
<script type="text/javascript">
function showProgress(data) {
var inputElement = data.source; // The HTML DOM input element.
var ajaxStatus = data.status; // Can be "begin", "success" and "complete"
var messageForInputElement = document.getElementById(inputElement.id + "_message");
switch (ajaxStatus) {
case "begin": // This is called right before ajax request is been sent.
messageForInputElement.innerHTML = "validating...";
break;
case "complete": // This is called right after ajax response is received.
messageForInputElement.innerHTML = "";
break;
case "success": // This is called when ajax response is successfully processed.
if (messageForInputElement.innerHTML.length == 0) { // So, no message has been set.
messageForInputElement.innerHTML = "valid!";
}
break;
}
}
</script>
</h:head>
<h:body>
<h:form id="form">
<h:panelGrid columns="3">
<h:outputLabel for="first_name" value="First Name" />
<h:inputText id="first_name" value="#{bean.firstName}" required="true">
<f:ajax event="blur" render="first_name_message" onevent="showProgress" />
</h:inputText>
<h:message id="first_name_message" for="first_name" />
<h:panelGroup />
<h:commandButton value="Submit" action="#{register.doSomething}">
<f:ajax execute="@form" render="@form" />
</h:commandButton>
<h:messages globalOnly="true" layout="table" />
</h:panelGrid>
</h:form>
</h:body>
</html>
And this is my bean:
@ManageBean
@ViewScope
..
public void doSomething(){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The Ajax4jsf's onbegin
and oncomplete
attributes are just extra abstractions of the existing onevent
attribute of the JSF2 standard <f:ajax>
tag. You only need to bring in some extra JavaScript code in to achieve the same functionality.
Here's a kickoff example:
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="input1" value="Input 1" />
<h:inputText id="input1" value="#{bean.input1}" required="true">
<f:ajax event="blur" render="input1_message" onevent="showProgress" />
</h:inputText>
<h:message id="input1_message" for="input1" />
<h:outputLabel for="input2" value="Input 2" />
<h:inputText id="input2" value="#{bean.input2}" required="true">
<f:ajax event="blur" render="input2_message" onevent="showProgress" />
</h:inputText>
<h:message id="input2_message" for="input2" />
<h:panelGroup />
<h:commandButton value="Submit" action="#{bean.submit}">
<f:ajax execute="@form" render="@form" />
</h:commandButton>
<h:messages globalOnly="true" layout="table" />
</h:panelGrid>
</h:form>
Here's a basic kickoff example the showProgress
function. The data
argument is a JS object whose properties are already described in tables 14-4 and 14-3 of the JSF specification.
function showProgress(data) {
var inputElement = data.source; // The HTML DOM input element.
var ajaxStatus = data.status; // Can be "begin", "success" and "complete"
var messageForInputElement = document.getElementById(inputElement.id + "_message");
switch (ajaxStatus) {
case "begin": // This is called right before ajax request is been sent.
messageForInputElement.innerHTML = "validating...";
break;
case "complete": // This is called right after ajax response is received.
messageForInputElement.innerHTML = "";
break;
case "success": // This is called when ajax response is successfully processed.
if (messageForInputElement.innerHTML.length == 0) { // So, no message has been set.
messageForInputElement.innerHTML = "valid!";
}
break;
}
}
You could substitute the innerHTML
of this kickoff example with for example images or adding/removing CSS style class on the message element which uses CSS background images, etc. This is not exactly trivial to keep crossbrowser compatible. I'd suggest to throw in some jQuery in there.
Basically, the Ajax4jsf's onbegin
and oncomplete
attributes removes the need that you've to write a whole JS function with a switch
to achieve the desired functionality. You could just refer directly some JavaScript functions which do the same as the lines inside the case
statements of the switch
. It's just an extra abstraction. You may want to consider using it so that amount of boilerplate code is minimized.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With