In this book, I have alone looked at the client side, including how to define a layout of a page using styles, and how to use JavaScript to modify the individual elements of the DOM tree. It takes place in the browser and without the server’s involvement. In this chapter, I will again look at the server side where the code is executed on the basis of a request from the browser and where the server then answers back with a response, which means that the browser should render the document again. With the help of Java online training JavaScript, it is possible to execute that form of a request/response in such a way that the user does not observes the page being updated and that the application essentially behaves in the same way as a standard desktop application. This technique is called Ajax.
Ajax is a family of technologies that enable JavaScript to perform tasks asynchronously when the browser sends requests to the server in the background, which then sends responses back to the client that can be used to update the DOM tree. The technology is widely used in all modern web applications.
You can basically associate ajax facilities with a JSF input component with the element of Ajax, which means an interaction between client and server, based on a particular event, an interaction performed asynchronously and parallel with the user using the application. A number of attributes are attached to an f: ajax element, where all, if not specified, has a default value:
- delay, which is a value specified in milliseconds and indicates the maximum size of a delay between request and response (none disables this feature).
- the event, which specifies the event for the component that triggers the Ajax request.
- execute, that specifies a list of components to be performed on the server.
- immediate, which is a boolean that indicates that the input value should be processed immediately.
- the event, that specifies the name of a JavaScript function to be performed.
- on error, that specifies the name of a JavaScript function for error handling.
- render, which is a list of components to be rendered after the ajax function.
For the execute and render attributes, the following terms are available for specifying
components:
components:
- @all, that means all components
- @form, that means all components in the form, that contains the component for the ajax function
- @this, that means the ajax functions parent component
- The components ID separated by spaces
- A JSF expression
To illustrate how ajax works, I want to show a number of examples that extend an existing
application with ajax functions, and it will be based on the application ChangeAddress3
from the book Java 11.
VALIDATION OF FIELDS
I have started with a copy of the project ChangeAddress3 from Java 11, and I have called the
copy for ChangeAddress1. If you open the application in the browser, you get them.
It works fine, but it would be more appropriate to validate each field immediately after the text is entered. As it is the server that validates the fields, a request must be made to the server for each field and Ajax can help, such that it happens completely transparent to the user. In fact, it is extremely simple and consists of changing the index.xhtml document as shown below:
It works fine, but it would be more appropriate to validate each field immediately after the text is entered. As it is the server that validates the fields, a request must be made to the server for each field, and Ajax can help, such that it happens completely transparent to the user. In fact, it is extremely simple and consists of changing the index.xhtml document as shown below:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC … >
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Change address</title>
<h:outputStylesheet library="css" name="styles.css"/>
</h:head>
<h:body>
<h1>Change address</h1>
<h:form>
<h:panelGrid columns="3" columnClasses="rightalign,leftalign,leftalign">
<h:outputLabel value="First name:" for="frstname"/>
<h:inputText id="frstname" label="First name" style="width: 300px"
value="#{indexController.frstname}" >
<f:validateRequired/>
<f:ajax event="blur" render="frstnameError"/>
</h:inputText>
<h:message for="frstname" class="error-message" id="frstnameError" />
<h:outputLabel value="Last name:" for="lastname"/>
<h:inputText id="lastname" label="Lastname" style="width: 200px"
value="#{indexController.lastname}" >
<f:validateRequired/>
<f:ajax event="blur" render="lastnameError"/>
</h:inputText>
<h:message for="lastname" class="error-message" id="lastnameError"/>
<h:outputLabel value="Address:" for="address"/>
<h:inputText id="address" label="Address" style="width: 300px"
value="#{indexController.address}" >
<f:validateRequired/>
<f:ajax event="blur" render="addressError"/>
</h:inputText>
<h:message for="address" class="error-message" id="addressError"/>
<h:outputLabel value="Zip code:" for="code" />
<h:inputText id="code" label="Zipcode" style="width: 60px"
value="#{indexController.code}">
<f:validateLength minimum="4" maximum="4"/>
<f:ajax event="blur" render="codeError"/>
</h:inputText>
<h:message for="code" class="error-message" id="codeError"/>
<h:outputLabel value="City:" for="city"/>
<h:inputText id="city" label="City" style="width: 200px"
value="#{indexController.city}" >
<f:validateRequired/>
<f:ajax event="blur" render="cityError"/>
</h:inputText>
<h:message for="city" class="error-message" id="cityError"/>
<h:outputLabel value="Email address:" for="email"/>
<h:inputText id="email" label="Email address" style="width: 300px"
value="#{indexController.email}">
<f:validator validatorId="emailValidator"/>
<f:ajax event="blur" render="emailError"/>
</h:inputText>
<h:message for="email" class="error-message" id="emailError"/>
<h:outputLabel value="Change date:" for="date"/>
<h:inputText id="date" label="Change date" required="true"
style="width: 100px" value="#{indexController.date}">
<f:validator validatorId="dateValidator"/>
<f:ajax event="blur" render="dateError"/>
</h:inputText>
<h:message for="date" class="error-message" id="dateError"/>
<h:outputLabel value="Job titel: " for="title"/>
<h:inputText id="title" required="false" style="width: 300px"
value="#{indexController.title}" />
<h:panelGroup/>
<h:commandButton value="Send" action="#{indexController.add()}" />
</h:panelGrid>
<a href="list.xhtml">Show addresses</a>
</h:form>
</h:body>
</html>
For example, if you consider the first field for entering the first name, you must specify whichIt works fine, but it would be more appropriate to validate each field immediately after the text is entered. As it is the server that validates the fields, a request must be made to the server for each field, and Ajax can help, such that it happens completely transparent to the user. In fact, it is extremely simple and consists of changing the index.xhtml document as shown below:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC … >
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Change address</title>
<h:outputStylesheet library="css" name="styles.css"/>
</h:head>
<h:body>
<h1>Change address</h1>
<h:form>
<h:panelGrid columns="3" columnClasses="rightalign,leftalign,leftalign">
<h:outputLabel value="First name:" for="frstname"/>
<h:inputText id="frstname" label="First name" style="width: 300px"
value="#{indexController.frstname}" >
<f:validateRequired/>
<f:ajax event="blur" render="frstnameError"/>
</h:inputText>
<h:message for="frstname" class="error-message" id="frstnameError" />
<h:outputLabel value="Last name:" for="lastname"/>
<h:inputText id="lastname" label="Lastname" style="width: 200px"
value="#{indexController.lastname}" >
<f:validateRequired/>
<f:ajax event="blur" render="lastnameError"/>
</h:inputText>
<h:message for="lastname" class="error-message" id="lastnameError"/>
<h:outputLabel value="Address:" for="address"/>
<h:inputText id="address" label="Address" style="width: 300px"
value="#{indexController.address}" >
<f:validateRequired/>
<f:ajax event="blur" render="addressError"/>
</h:inputText>
<h:message for="address" class="error-message" id="addressError"/>
<h:outputLabel value="Zip code:" for="code" />
<h:inputText id="code" label="Zipcode" style="width: 60px"
value="#{indexController.code}">
<f:validateLength minimum="4" maximum="4"/>
<f:ajax event="blur" render="codeError"/>
</h:inputText>
<h:message for="code" class="error-message" id="codeError"/>
<h:outputLabel value="City:" for="city"/>
<h:inputText id="city" label="City" style="width: 200px"
value="#{indexController.city}" >
<f:validateRequired/>
<f:ajax event="blur" render="cityError"/>
</h:inputText>
<h:message for="city" class="error-message" id="cityError"/>
<h:outputLabel value="Email address:" for="email"/>
<h:inputText id="email" label="Email address" style="width: 300px"
value="#{indexController.email}">
<f:validator validatorId="emailValidator"/>
<f:ajax event="blur" render="emailError"/>
</h:inputText>
<h:message for="email" class="error-message" id="emailError"/>
<h:outputLabel value="Change date:" for="date"/>
<h:inputText id="date" label="Change date" required="true"
style="width: 100px" value="#{indexController.date}">
<f:validator validatorId="dateValidator"/>
<f:ajax event="blur" render="dateError"/>
</h:inputText>
<h:message for="date" class="error-message" id="dateError"/>
<h:outputLabel value="Job titel: " for="title"/>
<h:inputText id="title" required="false" style="width: 300px"
value="#{indexController.title}" />
<h:panelGroup/>
<h:commandButton value="Send" action="#{indexController.add()}" />
</h:panelGrid>
<a href="list.xhtml">Show addresses</a>
</h:form>
</h:body>
</html>
validator to perform and then the element:
<f:ajax event="blur" render="frstnameError"/>
You should note that as an alternative, all validation functions could be written as javascript functions in this case, but in other cases, validation functions require a request to the server.
EXERCISE
In this exercise, you should make a change to the above example. start by creating a copy of the project change address1. you must now change the program so the field for entering the city name is readonly. The database data has a table zipcode, which is a list of Danish zip codes. You must change the validation of the field to zip code, so a zip code is only legal if there is an existing zip code in the table zipcode. If this is the case, the city name must be updated with the corresponding city name, and otherwise, the city name must be blank. The validation of the zip code field must still be done using ajax.
SUBMIT FIELDS WITHOUT RELOAD
SUBMIT FIELDS WITHOUT RELOAD
As next, I want to show how you with a submit a send all fields to the server, but without reloading the page. The benefits are not so big, but it gives a quieter window, as it all happens asynchronously, and the user thus, to a lesser extent, notes that data being sent to the server, and since the entire document does not be rendered again. I will use the same examples above, and I have started with a copy that I have calledChangeAddress2. In index.xhtml, I’ve changed in two places. Te Submit button now has an ajax function:
<h:commandButton value="Send" action="#{indexController.add()}" >
<f:ajax event="action" execute="@form" render="@all"/>
</h:commandButton>
and you should note that the function is triggered by an action event that the function should relate to all form felds and that all felds must be rendered. In addition, the last the link must be changed to an
h:commandLink:
<h:commandLink value="Show addresses" action="list.
xhtml" immediate="true" />
and here you should especially note the last attribute that is required because of the command should
not validate the form felds. Finally, the link on the page list.xhtml is changed to a commandLink
(what it should have been all the time).
<h:outputLabel value="Current date:" for="date"/>
<h:inputText id="date" label="Change date" readonly="true" tabindex="-1"
style="width: 100px" value="#{indexController.date}" />
You should note that there is no longer any ajax function associated with the component, and I have also changed the text in the corresponding label.
In order to initialize the field date I have in the class Person changed the constructor so it initializes the date field to the current date:
public Person()
Calendar cal = Calendar.getInstance();
date = String.format("%02d-%02d-%04d", cal.get(Calendar.DATE),
cal.get(Calendar.MONTH) + 1, cal.get(Calendar.YEAR));
cal.get(Calendar.MONTH) + 1, cal.get(Calendar.YEAR));
}
Finally, the ajax function of the submit button in index.xhtml is changed:
<h:commandButton value="Send" action="#{indexController.add()}" >
<f:ajax event="action" execute="frstname lastname address code city email title"
render="frstname lastname address code city email title"/>
</h:commandButton>
That is, I have now explicitly specifed which form felds are to be sent to the server, and
which form felds must be rendered after the function has been completed.
In this case, the advantage is, of course, limited, but in other contexts, it may matter, and remember that the whole idea of ajax is only to update that part of a page that is necessary.
I will make another change of the application, and I have started creating a copy that I have called ChangeAddress3. In index.xhtml the felds are validated with each their ajax function. You can actually achieve the same by encapsulating the felds to be validated in
an f: ajax element:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC … >
<html … >
<h:head>
…
</h:head>
<h:body>
<h1>Change address</h1>
<h:form id="mainForm">
<h:panelGrid columns="3" columnClasses="rightalign,leftalign,leftalign">
<f:ajax event="blur" render="frstnameError lastnameError addressError codeError
cityError emailError">
cityError emailError">
<h:inputText id="frstname" label="First name" style="width: 300px"
value="#{indexController.frstname}" >
<f:validateRequired/>
<f:validateRequired/>
</h:inputText>
<h:message for="frstname" class="error-message" id="frstnameError" />
<h:outputLabel value="Last name:" for="lastname"/>
<h:inputText id="lastname" label="Lastname" style="width: 200px"
value="#{indexController.lastname}" >
<f:validateRequired/>
</h:inputText>
<h:message for="lastname" class="error-message" id="lastnameError"/>
<h:outputLabel value="Address:" for="address"/>
<h:inputText id="address" label="Address" style="width: 300px"
value="#{indexController.address}" >
<f:validateRequired/>
</h:inputText>
<h:message for="address" class="error-message" id="addressError"/>
<h:outputLabel value="Zip code:" for="code" />
<h:inputText id="code" label="Zipcode" style="width: 60px"
value="#{indexController.code}">
<f:validateLength minimum="4" maximum="4"/>
</h:inputText>
<h:message for="code" class="error-message" id="codeError"/>
<h:outputLabel value="City:" for="city"/>
<h:inputText id="city" label="City" style="width: 200px"
value="#{indexController.city}" >
<f:validateRequired/>
</h:inputText>
<h:message for="city" class="error-message" id="cityError"/>
<h:inputText id="email" label="Email address" style="width: 300px"
value="#{indexController.email}">
<f:validator validatorId="emailValidator"/>
</h:inputText>
<h:message for="email" class="error-message" id="emailError"/>
</f:ajax>
<h:outputLabel value="Current date:" for="date"/>
<h:inputText id="date" label="Change date" readonly="true" tabindex="-1"
style="width: 100px" value="#{indexController.date}" />
<h:message for="date" class="error-message" id="dateError"/>
<h:outputLabel value="Job titel: " for="title"/>
<h:inputText id="title" required="false" style="width: 300px"
value="#{indexController.title}" />
<h:panelGroup/>
<h:commandButton value="Send" action="#{indexController.add()}" >
<f:ajax event="action"
execute="frstname lastname address code city email title"
render="frstname lastname address code city email title"/>
render="frstname lastname address code city email title"/>
</h:commandButton>
</h:panelGrid>
<h:commandLink value="Show addresses" action="list.xhtml" immediate="true" />
</h:form>
<h:form id="form2">
</h:form>
</h:body>
</html>
The validation takes place in the same way, but the writing method is all the more straightforward. Note that it is necessary to specify the felds (for error messages) to be
rendered. However, there is one difference since validation occurs every time a lost focus-event occurs and hence each time an input field is left. This means that it is only the error
message regarding the relevant input component that appears – which may sometimes also
be the most appropriate.
CONVERTERS
In the following example, I will show the use of converters where you can attach a converter to an input component. It has not directly to do with the Ajax but is often used in conjunction with Ajax. The example is the same as above, and I have started with a copy of
ChangeAddress3, which I have called ChangeAddress4. As an example of using converters, it must be such that the city name will automatically be converted to uppercase letters, while the email address will automatically be converted to lowercase letters. Such a converter can
be written as follows:
package change address.validators;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
@FacesConverter("changeaddress.validators.UpperConverter")
public class UpperConverter implements Converter
{
@Override
public Object getAsObject
(FacesContext context, UIComponent component, String value)
{
return value.toUpperCase();
}
@Override
public String getAsString
(FacesContext context, UIComponent component, Object value)
{
return value.toString().toUpperCase();
}
and is relatively trivial. There is a corresponding converter class named LowerConverter. As an example of using a slightly more interesting converter, the application has been changed so that you can edit the datefield again, but I have preserved that the field is initialized with today. On the other hand, I want greater flexibility with regard to entering a date, so it should be allowed to use spaces instead of hyphens. To solve it, I have added the following
converter to the program:
package change address.validators;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
@FacesConverter("changeaddress.validators.DateConverter")
public class DateConverter implements Converter
{
@Override
public Object getAsObject
(FacesContext context, UIComponent component, String value)
{
String[] elems = value.split("-");
if (elems.length == 3) return value;
elems = value.split("/");
if (elems.length == 3) return value.replace('/', '-');
elems = value.split(" ");
if (elems.length == 3) return value.replace(' ', '-');
return value;
}
@Override
public String getAsString
(FacesContext context, UIComponent component, Object value)
{
String text = value.toString();
String[] elems = text.split("-");
if (elems.length == 3) return text;
elems = text.split("/");
if (elems.length == 3) return text.replace('/', '-');
elems = text.split(" ");
if (elems.length == 3) return text.replace(' ', '-');
return value.toString();
}
}
<h:inputText id="date" label="Change date" style="width: 100px"
value="#{indexController.date}" >
<f:validator validatorId="dateValidator"/>
<f:converter converterId="changeaddress.validators.DateConverter"/>
</h:inputText>
<h:message for="date" class="error-message" id="dateError"/>
The other two converters are used in the same way. since the value entered in the field must be updated ed immediately after the entry, the f: ajax element must also be updated:
address error code error cityError emailError dateError">
Looking at the input component date, it has both a validator and a converter, and here you should be
aware of the order of when the methods are performed:
1. getAsObject() // the class DateConverter
2. getAsString() // the class DateConverter
JSF LISTENERS
JSF components can raise different events when rendered (where the names tell when the
events occur)
events occur)
- preRenderComponent,
- postAddToView
- preValidate
- postValidate
- postValidate
You can define listeners of these events, which are Java code, which is performed on the server. As an example, I have created a copy ofthe projectChangeAddress4 and called the copy ChangeAddress5. First of all, I have changed the code for index.xhtml so that, as in
ChangeAddress1, it has an ajax function for each input component. As the next step, the
IndexController is expanded with two methods:
public String isWeekend()
{
String[] elems = person.getDate().split("-");
Calendar date = new GregorianCalendar(Integer.parseInt(elems[2]),
Integer.parseInt(elems[1]) – 1, Integer.parseInt(elems[0]));
return date.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY ||
date.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ? "red" : "darkgreen";
}
public void checkForWeekend(ComponentSystemEvent event)
{
UIOutput output = (UIOutput) event.getComponent();
if (isWeekend().equals("red")) output.setValue("Weekend");
else output.setValue("Everyday");
}
The class Person has a property date initialized with today and the first method test where this date is for a weekend (Saturday or Sunday). If that is the case, the method returns the text red and otherwise the text dark green. The next method is the listener method. It's a parameter
is an event and the method determines a reference to the component to which the event relates. If the Person object’sdate property is a date of a weekend, the component’s value
is set to Weekend and otherwise to Everyday.
The two methods are basically simple Java methods, and I will now show how they can be used as event handlers in index.xhtml. Te form is expanded with a new element of the type output text (the only requirement is that it is a component with a value property):
<h:message for="date" class="error-message" id="dateError"/>
<h:panelGroup/>
The two methods are basically simple Java methods, and I will now show how they can be used as event handlers in index.xhtml. Te form is expanded with a new element of the type output text (the only requirement is that it is a component with a value property):
<h:outputLabel value="Enter date:" for="date"/>
<h:inputText id="date" label="Change date" style="width: 100px"
value="#{indexController.date}" >
<f:validator validatorId="dateValidator"/>
<f:converter converterId="changeaddress.validators.DateConverter"/>
<f:ajax event="blur" render="dateError weekend"/>
</h:inputText>
<h:message for="date" class="error-message" id="dateError"/>
<h:panelGroup/>
<h:outputText id="weekend"
style="font-style: italic; color: #{indexController.isWeekend()};">
<f:event type="preRenderComponent"
listener="#{indexController.checkForWeekend}"/>
</h:outputText>
<h:panelGroup/>
The new elements have an in with the value weekend as well as a style attribute, where you should primarily note that the value of color is determined by the return value from the method isWeekend(), which is either red or dark green. As a result, the text appears either as red or green. Finally, the element defines an event of the type preRenderComonent. That is, the event handler (the element’s listener) is performed before the element is rendered and the handler is the method check for the weekend() in the controller class. It is executed each
time the element is rendered, which naturally occurs when the page is rendered, but it also
happens when the input component to date is changed, as the ajax function indicates that
the element with id weekend must be rendered.
Ingin memainkan permainan BandarQ dengan cukup mudah dan cepat, disarankan untuk mendapatkan dan menggunakan Bobol Server Judi BandarQ.
ReplyDelete