I have 2 outputText fields, 1 required field and 1 optional field. How can I concat, or append all of the values and set it as a single model property?
<h:outputText value="AT-" />
<h:outputText value="#{yearOfDate}"/>
<p:inputMask value="#{requiredRefNo}" required="true" mask="9999"/>
<p:inputMask value="#{optionalRefNo}" mask="aa"/>
In the given example I have for example the string AT-2012-6060-VI. How can I append all of the values and set it as a single model property?
For you it would probably be the easiest to create a composite component for this with a backing component which extends UIInput and wherein the desired format is returned by UIInput#getSubmittedValue().
Here's a kickoff example in its simplest form:
/resources/components/refNo.xhtml
<ui:component
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
>
<cc:interface componentType="refNoComposite" />
<cc:implementation>
AT-#{cc.year}-<p:inputMask id="ref1" required="true" mask="9999"/>-<p:inputMask id="ref2" mask="aa"/>
</cc:implementation>
</ui:component>
com.example.RefNoComposite
#FacesComponent("refNoComposite")
public class RefNoComposite extends UIInput implements NamingContainer {
public RefNoComposite() {
getStateHelper().put("year", new SimpleDateFormat("yyyy").format(new Date()));
}
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
#Override
public Object getSubmittedValue() {
return new StringBuilder()
.append("AT")
.append('-')
.append(getYear())
.append('-')
.append(((UIInput) findComponent("ref1")).getSubmittedValue())
.append('-')
.append(((UIInput) findComponent("ref2")).getSubmittedValue())
.toString();
}
public String getYear() {
return (String) getStateHelper().eval("year");
}
}
Usage example in a random Facelets page:
xmlns:cc="http://java.sun.com/jsf/composite/components"
...
<h:form>
<cc:refNo value="#{bean.value}" />
<p:commandButton value="submit" action="#{bean.submit}" />
</h:form>
Note: if you'd like to validate the value as well, you'd like to override the UIInput#validateValue() method in the backing component. The 2nd argument is by the way exactly the getSubmittedValue().
Related
This question already has answers here:
Validation Error: Value is not valid
(3 answers)
Closed 7 years ago.
I have a jsf form in my application which should display several input fields for creating / editing employees. There exists several departments which I want to display with a <h:selectOneMenu>. My other components are basically primefaces components.
If I select an existing employee from my datatable, the department is set correctly (in frontend and bean). I checked the converter and it's getAsString() method in debugging mode. Both seem to work fine.
But when I refresh the page with [F5] it changes the value in the <h:selectOneMenu> back to it's previous one but the bean's value is still fine. It seems that the binding between my session bean and the jsf component isn't working properly.
In addition, there's another problem when I want to save any employee. The validation shows me that the selectOneMenu value is invalid. This error occurs after the getAsObject() method successfully returns my department pojo. I didn't define any validators on this specific component but I use several input components who must not be empty. This error might occur because there's a problem with setting the value as I stated above.
DepartmentConverter.java
#ManagedBean(name="departmentConverter")
public class DepartmentConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
DepartmentDAOImpl deptUtils = new DepartmentDAOImpl();
try {
int code = Integer.parseInt(value);
return deptUtils.getDepartmentById(code);
} catch (NumberFormatException nfe) {
System.out.println("Couldn't transform department code from string to int");
nfe.printStackTrace();
}
return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return ((Department) value).getCode() + "";
}
}
SampleJSFBean.java
#ManagedBean(name = "sampleBean")
#SessionScoped
public class SampleJSFBean {
private Task employee;
private List<Task> employees;
private List<Department> departments;
private Department department;
public String showEditEmployeePanel() {
// shows panel
}
public String updateEmployee() {
// saves employee
}
// getter and setter
}
registration.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui" template="/templates/BasicTemplate.xhtml">
<ui:define name="content">
<h:form id="formResult">
<p:panel>
<p:dataTable id="employee" var="task" value="#{sampleBean.employees}">
<p:column headerText="Code">
<h:outputText value="#{task.employee.code}" />
</p:column>
<p:column headerText="Name">
<h:outputText value="#{task.employee.lastname}" />
</p:column>
<p:column headerText="Department">
<h:outputText value="#{task.employee.department.name}" />
</p:column>
<p:column headerText="edit">
<p:commandButton id="btnMut" icon="ui-icon-pencil" title="edit employee" disabled="#{task.jobActive == true}" action="#{sampleBean.showEditEmployeePanel}"
update=":formEmployee" resetValues="true">
<f:setPropertyActionListener value="#{task}" target="#{sampleBean.task}" />
</p:commandButton>
</p:column>
</p:dataTable>
</p:panel>
</h:form>
<h:form id="formEmployee">
<p:growl autoUpdate="false" />
<p:panel id="panelEmployee">
<h:outputText value="Lastname" styleClass="labelForm" />
<p:inputText id="inputLastname" value="#{sampleBean.task.employee.lastname}" required="true" requiredMessage="Please enter lastname." />
<br />
<h:outputText value="Department" styleClass="labelForm" />
<h:selectOneMenu value="#{sampleBean.department}" converter="#{departmentConverter}">
<f:selectItems value="#{sampleBean.departments}" var="dept" itemLabel="#{dept.code} - #{dept.name}" />
</h:selectOneMenu>
<br />
<p:commandButton value="save" action="#{sampleBean.updateEmployee}" icon="ui-icon-disk" update=":formResult :formEmployee" />
</p:panel>
</h:form>
</ui:define>
Have you tried with primefaces component instead <h:selectOneMenu> use <p:selectOneMenu>.
I'm not sure it helps, but I always use primeFaces's selectOneMenu and always works.
How can i switch my validator in a component dependence on a boolean.
I have a selectBooleanCheckbox and when its true i want use FirstValidator else i want use SecondValidator. I found nothing about this "special" case.
Nothing special only for example code:
Xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<h:head>
</h:head>
<h:body>
<h:form>
<h:selectBooleanCheckbox value="#{testBean.firstValidator}"/>
<h:inputText>
<f:validator validatorId="FirstValidator" />
</h:inputText>
<h:commandButton value="Test" />
<h:messages />
</h:form>
</h:body>
</html>
Bean:
#ManagedBean
#ViewScoped
public class TestBean implements Serializable{
private boolean firstValidator;
public boolean isfirstValidator() {
return firstValidator;
}
public void setfirstValidator(boolean firstValidator) {
this.firstValidator = firstValidator;
}
}
Validator1:
#FacesValidator("FirstValidator")
public class FirstValidator implements Validator{
#Override
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
String valueAsString = (String) value;
if(valueAsString.contains("a")){
throw new ValidatorException(new FacesMessage("Fail!"));
}
}
}
Validator2:
#FacesValidator("SecondValidator")
public class SecondValidator implements Validator{
#Override
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
String valueAsString = (String) value;
if(valueAsString.contains("b")){
throw new ValidatorException(new FacesMessage("Fail2!"));
}
}
}
Just set/disable the validator depending on checkbox's value. You only need to make sure that you pick the checked value as available during view build time (which runs during restore view phase). So you definitely can't use the model value #{testBean.firstValidator} for this (which is only set during update model values phase). You'd need to determine the HTTP request parameter instead. It's empty if the checkbox is unchecked, otherwise it's not empty.
First bind the checkbox component to the view (not to a bean!) via binding attribute:
<h:selectBooleanCheckbox binding="#{checkbox}" ... />
This way the request parameter can be dynamically obtained as #{param[checkbox.clientId]}.
Now you can use either conditional setting of validator ID:
<f:validator validatorId="#{empty param[checkbox.clientId] ? 'firstValidator' : 'secondValidator'}" />
Or conditional setting the validator's disabled attribute:
<f:validator validatorId="firstValidator" disabled="#{not empty param[checkbox.clientId]}" />
<f:validator validatorId="secondValidator" disabled="#{empty param[checkbox.clientId]}" />
Note that I altered the validator IDs as per Java instance variable naming conventions. You also don't do as follows in normal Java code, right?
Validator FirstValidator = new FirstValidator();
I have a JSF 2 form like this:
<h:form>
<h:panelGrid columns="2">
<a4j:repeat value="#{dialog.departments}" var="depart">
<h:inputText value="#{depart.name}"/>
<h:selectOneRadio value="#{depart.hasSubdepartment}">
<f:ajax render="#form" execute="#form" immediate="true"/>
<f:selectItem itemValue="#{true}"/>
<f:selectItem itemValue="#{false}"/>
</h:selectOneRadio>
<a4j:repeat value="#{depart.subdepartments}" var="sub" rendered="#{depart.hasSubdepartment}">
<h:inputText value="#{sub.name}"/>
<h:outputText value=" " />
</a4j:repeat>
</a4j:repeat>
</h:panelGrid>
</h:form>
I have simply the form. As you could see, this form displays data structure of departments like a tree.
What I want to implements is that if user switch the radio button to true, the sub-departments will be displayed, if switch to false, the sub-departments will be hidden.
The problem is that:
If the execute value of the f:ajax tag is set to #form, the validation of the backing beans such as #NotNull and #Size will be called. But we don't want to call the validation now since we do not want to save the data now.
If the execute value of the f:ajax tag is set to #this, it seems that the after the ajax request, the value of the radio reverts. For example, if the radio value is false, and we click true, then after the ajax request, the value go back to false, and the sub-department part is not rendered. This will not happen if execute is set to #form.
Thanks very much if you have any idea or hint.
I don't have a Richfaces integrated testing environment, however I've achieved what you want in plain JSF (that's why it could be an ajax4jsf specific issue). Here you have a test case which works and follows SSCCE standards. Tested with Mojarra 2.1.26 & Tomcat 6:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
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 />
<h:body>
<h:form>
<h:panelGrid columns="2">
<ui:repeat value="#{dialog.departments}" var="depart">
<h:inputText value="#{depart.name}" />
<h:selectOneRadio value="#{depart.hasSubdepartments}">
<f:ajax render="#form" immediate="true" />
<f:selectItem itemValue="#{true}" />
<f:selectItem itemValue="#{false}" />
</h:selectOneRadio>
<h:panelGroup id="subdepartmentPanel"
rendered="#{depart.hasSubdepartments}">
<ui:repeat value="#{depart.subdepartments}" var="sub">
<h:inputText value="#{sub.name}" />
</ui:repeat>
</h:panelGroup>
</ui:repeat>
</h:panelGrid>
</h:form>
</h:body>
</html>
#ManagedBean
#ViewScoped
public class Dialog {
public class Department {
private String name;
private List<Department> subdepartments = new ArrayList<Dialog.Department>();
private boolean hasSubdepartments;
public Department(String name) {
this.name = name;
}
public String getName() {
return name;
}
public List<Department> getSubdepartments() {
return subdepartments;
}
public boolean isHasSubdepartments() {
return hasSubdepartments;
}
public void setHasSubdepartments(boolean hasSubdepartments) {
this.hasSubdepartments = hasSubdepartments;
}
public void setName(String name) {
this.name = name;
}
public void setSubdepartments(List<Department> subdepartments) {
this.subdepartments = subdepartments;
}
}
private List<Department> departments = new ArrayList<Dialog.Department>();
public Dialog() {
// Create departments and subdepartments
departments.add(new Department("First Department"));
Department d = new Department("Second department");
d.getSubdepartments().add(new Department("Subdepartment"));
departments.add(d);
}
public List<Department> getDepartments() {
return departments;
}
}
As soon as a composite which encapsulates a commandButton is included in my .xhtml, the viewscoped bean is reinitialized no matter which commandButton is used. Is my composite wrong? Please let me know because I realy would like to use composites for my buttons.
Simplyfied testcase:
#ManagedBean
#ViewScoped
public class Test implements Serializable {
private static final long serialVersionUID = 123456L;
private static int i = 0;
private int counter;
private String table;
private transient DataModel<String> model;
#PostConstruct
public void test() {
System.out.println(".......... PostConstruct");
i++;
List<String> modelData = new ArrayList<String>();
modelData.add("hello");
modelData.add("world");
model = new ListDataModel<String>(modelData);
}
public int getCounter() {
return counter;
}
public String getTable() {
return table;
}
public DataModel<String> getModel() {
return model;
}
public void tableListener() {
String data = model.getRowData();
table = data.toUpperCase();
}
}
No matter which button is clicked (2nd or 3th column), the postConstruct method is called over and over again
<h:form>
<h:dataTable style="width: 40em" var="line" value="#{test.model}">
<h:column>
<f:facet name="header">string</f:facet>
#{line}
</h:column>
<h:column>
<f:facet name="header">actie...1</f:facet>
<h:commandButton value="toUpper" immediate="true" >
<f:ajax event="click" execute="#form" render=":testTable" listener="#{test.tableListener}" />
</h:commandButton>
</h:column>
<h:column>
<f:facet name="header">actie...2</f:facet>
<cmp:rowAction managedBean="#{test}" label="button" listener="tableListener"
tooltip="test via composite" img="stop.png" render=":testTable"/>
</h:column>
</h:dataTable>
</h:form>
As soon as the last column (header actie...2) is removed, then the #PostConstruct is called only once, as expected.
Why does the presence of my composite forces to reinitialize the viewscoped bean? What's wrong with my composite, it works, but it shouldn't reinitialize the managed bean:
<?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:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<!-- INTERFACE -->
<cc:interface>
<cc:attribute name="label" required="true"/>
<cc:attribute name="render"/>
<cc:attribute name="tooltip"/>
<cc:attribute name="img"/>
<cc:attribute name="listener" required="true"/>
<cc:attribute name="managedBean" required="true"/>
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<h:commandButton id="btn_#{cc.attrs.label}" title="#{cc.attrs.tooltip}" immediate="true"
image="/resources/img/#{cc.attrs.img}">
<f:ajax event="click" execute="#form" render="#{cc.attrs.render}" listener="#{cc.attrs.managedBean[cc.attrs.listener]}" />
</h:commandButton>
</cc:implementation>
based on this post, JSF 2 - How can I add an Ajax listener method to composite component interface? i've found a solution. The problem was the declaration of the listener attribute cc:attribute name="listener" required="true"/> it should be cc:attribute name="listener" method-signature="void listener()" required="true"/>
There is still one (in my case minor) problem as mentioned by BalusC in the previously mentioned post: I can't us the AjaxBehvaiorEvent. I'm using Netbeans 6.9.1, Gfish3.1 and Mojarra2.1.1
I have an h:inputText and an h:message connected to it:
<h:inputText id="myText" value="#{myController.myText}" />
<a4j:outputPanel>
<h:message for="myText" .../>
</a4j:outputPanel>
I want to send a message to it from java, in a manner like:
FacesContext.getCurrentInstance().addMessage(arg0, arg1);
which is sent to h:messages, but to a specific id in a specific form.
How can I do this? (Without implementing validation bean or validation method - meaning without throwing validation exception).
You need to provide the so called client id, which you'll find on UIComponent.
The following is a quick example of how to use this.
Consider the following bean:
#ManagedBean
#RequestScoped
public class ComponentMsgBean {
private UIComponent component;
public UIComponent getComponent() {
return component;
}
public void setComponent(UIComponent component) {
this.component = component;
}
public String doAction() {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(component.getClientId(), new FacesMessage("Test msg"));
return "";
}
}
being used on the following Facelet:
<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"
>
<h:body>
<h:form>
<h:outputText id="test" value="test component" binding="#{componentMsgBean.component}"/>
<h:message for="test"/>
<h:commandButton value="click me" action="#{componentMsgBean.doAction}" />
</h:form>
</h:body>
</html>
This will add a Faces message with content "Test msg" for the outputText component used in the example.
Another way to do that is: give an ID to the form, like "form1", then, when add the message, the clientId is "form1:test".