In the last tutorial, we saw how to create and register a custom converter. This tutorial will demonstrate, how to pass attributes to the custom converter by using <f:converter /> and <f:attribute /> tags.
Example
JSF page
src/main/webapp/index.xhtml<?xml version="1.0" encoding="UTF-8"?>
<!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">
<h:head></h:head>
<h:body>
<h2>JSF custom converter example</h2>
<h:form>
<h:panelGrid columns="2">
<h:outputLabel for="wph" value="Work Phone: "/>
<h:inputText id="wph" value="#{phoneBean.workPhone}">
<f:converter converterId="phConverter"/>
<f:attribute name="format" value="standard"/>
</h:inputText>
<h:outputLabel for="cph" value="Cell Phone: "/>
<h:inputText id="cph" value="#{phoneBean.cellPhone}">
<f:converter converterId="phConverter"/>
<f:attribute name="format" value="plain"/>
</h:inputText>
<h:commandButton value="Submit" action="result.xhtml"/>
</h:panelGrid>
<div>
work Phone:
<h:outputText value = "#{phoneBean.workPhone}">
<!--the default format will be used-->
<f:converter converterId="phConverter"/>
</h:outputText>
</div>
<div>
Cell Phone:
<!--no formatting will be used-->
<h:outputText value = "#{phoneBean.cellPhone}"/>
</div>
</h:form>
</h:body>
</html>
The Converter
@FacesConverter("phConverter")
public class PhoneConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
Map<String, Object> attributes = component.getAttributes();
String formatString = (String) attributes.get("format");
Phone phone = PhoneFormat.parse(formatString, value);
return phone;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
Phone phone = (Phone) value;
Map<String, Object> attributes = component.getAttributes();
String formatString = (String) attributes.get("format");
return PhoneFormat.format(formatString, phone);
}
}
public enum PhoneFormat {
STANDARD("(\\d{3})-(\\d{3})-(\\d{4})") {
@Override
String format(Phone phone) {
return phone.getAreaCode() +
"-" + phone.getExchangeCode() +
"-" + phone.getLineNumber();
}
},
PLAIN("(\\d{3})(\\d{3})(\\d{4})") {
@Override
String format(Phone phone) {
return phone.getAreaCode() +
phone.getExchangeCode() +
phone.getLineNumber();
}
};
private final Pattern compiledPattern;
PhoneFormat(String pattern) {
compiledPattern = Pattern.compile(pattern);
}
public static PhoneFormat getPhoneFormat(String formatString) {
try {
return valueOf(formatString.toUpperCase());
} catch (IllegalArgumentException | NullPointerException e) {
//returning default format;
return STANDARD;
}
}
public static Phone parse(String formatString, String value) {
PhoneFormat phoneFormat = getPhoneFormat(formatString);
Matcher matcher = phoneFormat.compiledPattern.matcher(value);
if (!matcher.matches()) {
throw new RuntimeException(
String.format("invalid input: %s. The valid format is of type %s%n",
value, phoneFormat.compiledPattern.pattern()));
}
String areaCode = matcher.group(1);
String exchange = matcher.group(2);
String line = matcher.group(3);
return new Phone(areaCode, exchange, line);
}
public static String format(String formatString, Phone phone) {
PhoneFormat phoneFormat = getPhoneFormat(formatString);
return phoneFormat.format(phone);
}
abstract String format(Phone phone);
}
public class Phone {
private String areaCode;
private String exchangeCode;
private String lineNumber;
.............
}
Managed Bean
@ManagedBean
@ViewScoped
public class PhoneBean {
private Phone workPhone;
private Phone cellPhone;
public Phone getWorkPhone() {
return workPhone;
}
public void setWorkPhone(Phone phone) {
this.workPhone = phone;
}
public Phone getCellPhone() {
return cellPhone;
}
public void setCellPhone(Phone cellPhone) {
this.cellPhone = cellPhone;
}
}
To try examples, run embedded tomcat (configured in pom.xml of example project below):
mvn tomcat7:run-war
Output
On entering and submitting valid phone numbers:
Example ProjectDependencies and Technologies Used: - jsf-api 2.2.14:
This is the master POM file for Oracle's Implementation of the JSF 2.2 Specification.
- jsf-impl 2.2.14:
This is the master POM file for Oracle's Implementation of the JSF 2.2 Specification.
- JDK 1.8
- Maven 3.3.9
|