编辑:问题是当复合组件包装在 ui:repeat 或 h:datatable 以及 ap:dialog 中时
使用http://balusc.blogspot.de/2013/01/composite-component-with-multiple-input.html我在 ap:dialog 中提交包含复合组件的表单似乎有问题。
调用普通 p:boolean 和此类字段的设置器,但不会调用来自复合组件的设置器,尽管 getSubmittedvalue 是。
初始值为空,当不在模态 p:dialog 中时,同样的工作。
我可以在调试/配置文件模式下清楚地看到它。
INFO: Initializing Mojarra 2.1.6 (SNAPSHOT 20111206) for context '/webclient'
INFO: Running on PrimeFaces 3.5
INFO: Running on PrimeFaces Extensions 0.6.3
编辑:也尝试将初始值设置为默认值,即不为空。同样的事情发生了......二传手不会被调用。
我必须再次强调,当不在 p:dialog 中时,相同的东西有效(如果这很重要,appendtobody 为 true)。
SSCCE
控制器:
@ManagedBean
@ViewScoped
public class TestController implements Serializable {
List<TestSelect> testbeanList;
List<BeanObject> beanList;
@PostConstruct
void init() {
testbeanList = new ArrayList<TestSelect>() {
{
add(new TestSelect("km"));
add(new TestSelect("g"));
add(new TestSelect("lbs"));
}
};
beanList = new ArrayList<BeanObject>() {
{
add(new BeanObject(2.0d, "lbs"));
add(new BeanObject(3.0d, "g"));
add(new BeanObject(4.0d, "km"));
}
};
}
public List<TestSelect> getTestbeanList() {
return testbeanList;
}
public void setTestbeanList(List<TestSelect> testbeanList) {
this.testbeanList = testbeanList;
}
public BeanObject getBeanObject() {
return BeanObject;
}
public void setBeanObject(BeanObject BeanObject) {
this.BeanObject = BeanObject;
}
}
豆:
public class BeanObject {
double val;
String type;
public BeanObject(double val, String type) {
super();
this.val = val;
this.type = type;
}
public double getVal() {
return val;
}
public void setVal(double val) {
this.val = val;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
小面:
<!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"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:pe="http://primefaces.org/ui/extensions"
>
<h:head>
</h:head>
<h:body>
<p:dialog widgetVar="dlg" appendToBody="true">
<h:form>
<ui:repeat var="uom" value="#{testController.beanList}">
<usb:uom value="#{uom}" list="#{testController.testBeanList}"/>
</ui:repeat>
<p:commandButton process="@form" action="null" value="submit" />
</h:form>
</p:dialog>
<h:form>
<p:commandButton onclick="dlg.show();" value="show dlg" />
</h:form>
</h:body>
</html>
面组件:
@FacesComponent("testComponent") 公共类 TestComponent 扩展 UIInput 实现 NamingContainer {
/** The Constant LOGGER. */
private static final Logger LOGGER = Logger.getLogger(TestComponent.class);
// Fields
// -------------------------------------------------------------------------------------
/** The measure. */
private UIInput measure;
/** The unit. */
private UISelectOne unit;
// Actions
// ------------------------------------------------------------------------------------
/*
* (non-Javadoc)
*
* @see javax.faces.component.UIInput#getFamily()
*/
/**
* Gets the family.
*
* @return the family
*/
@Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
/*
* (non-Javadoc)
*
* @see
* javax.faces.component.UIComponent#encodeAll(javax.faces.context.FacesContext
* )
*/
/**
* Encode all.
*
* @param context
* the context
* @throws IOException
* Signals that an I/O exception has occurred.
*/
@Override
public void encodeBegin(FacesContext context) throws IOException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("encodeAll BEGIN");
}
Object testTest = getAttributeValue("value", "");
String val = null;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("testTest -> " + testTest.toString());
}
if (testTest instanceof BeanObject) {
val = testTest.toString();
} else {
val = (String) testTest;
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("val -> " + val);
}
if (!val.equals("")) {
String[] testSplitted = val.split(" ");
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("testSplitted -> " + testSplitted);
for (int i = 0; i < testSplitted.length; i++) {
LOGGER.debug("testSplitted it -> " + testSplitted[i]);
}
}
measure.setValue(testSplitted[0]);
unit.setValue(testSplitted[1]);
}
super.encodeBegin(context);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("encodeAll END");
}
}
/**
* Gets the converted value.
*
* @param context
* the context
* @param submittedValue
* the submitted value
* @return the converted value
*/
@Override
protected Object getConvertedValue(FacesContext context, Object submittedValue) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("getConvertedValue()");
}
String[] tmpVal = ((String) getSubmittedValue()).split(" ");
if (LOGGER.isDebugEnabled()) {
for (int i = 0; i < tmpVal.length; i++) {
LOGGER.debug("unit and val -> " + i + " -> " + tmpVal[i]);
}
}
if (tmpVal == null || Strings.isNullOrEmpty(tmpVal[0])) {
return null;
}
BeanObject test = new BeanObject(Double.parseDouble(tmpVal[0]), tmpVal[1]);
return test;
}
/*
* (non-Javadoc)
*
* @see javax.faces.component.UIInput#getSubmittedValue()
*/
/**
* Gets the submitted value.
*
* @return the submitted value
*/
@Override
public Object getSubmittedValue() {
if (Strings.isNullOrEmpty((String) getMeasure().getValue())) {
return null;
}
if (Strings.isNullOrEmpty((String) getUnit().getValue())) {
Object value = getAttributeValue("value", "");
if (value instanceof AttributeObject) {
LOGGER.error("yes1");
}
if (value instanceof IAttributeObject) {
LOGGER.error("yes2");
}
LOGGER.error("getSubmittedValue -> " + value.toString());
}
String submitVal = (String) getMeasure().getValue() + " " + (String) getUnit().getValue();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("getSubmittedValue()" + submitVal);
}
return submitVal;
}
// Helpers
// ------------------------------------------------------------------------------------
/**
* Return specified attribute value or otherwise the specified default if
* it's null.
*
* @param <T>
* the generic type
* @param key
* the key
* @param defaultValue
* the default value
* @return the attribute value
*/
@SuppressWarnings("unchecked")
private <T> T getAttributeValue(String key, T defaultValue) {
T value = (T) getAttributes().get(key);
return (value != null) ? value : defaultValue;
}
// Getters/setters
// ----------------------------------------------------------------------------
/**
* Gets the measure.
*
* @return the measure
*/
public UIInput getMeasure() {
return measure;
}
/**
* Gets the unit.
*
* @return the unit
*/
public UISelectOne getUnit() {
return unit;
}
/**
* Sets the unit.
*
* @param unit
* the new unit
*/
public void setUnit(UISelectOne unit) {
this.unit = unit;
}
/**
* Sets the measure.
*
* @param measure
* the new measure
*/
public void setMeasure(UIInput measure) {
this.measure = measure;
}
}
组件面:
<ui:composition
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"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:pe="http://primefaces.org/ui/extensions">
<cc:interface componentType="testComponent">
<cc:attribute type="java.lang.Object" name="value" required="true" />
<cc:attribute type="java.util.List" name="list"/>
</cc:interface>
<cc:implementation>
<h:panelGrid columns="3">
<p:inputText id="measure" binding="#{cc.measure}">
<f:ajax render="unit" />
</p:inputText>
<p:selectOneMenu id="unit" binding="#{cc.unit}">
<f:selectItem noSelectionOption="true" itemLabel=" " itemValue="" />
<f:selectItems value="#{cc.attrs.list}" var="option" itemLabel="#{option.getShortName()}" itemValue="#{option.getShortName()}" />
<f:ajax render="measure" />
</p:selectOneMenu>
</h:panelGrid>
</cc:implementation>
</ui:composition>
助手选择bean:
public class TestSelect {
private static final Logger LOGGER = Logger.getLogger(TestController.class);
String ShortName;
public TestSelect(String shortName) {
super();
ShortName = shortName;
}
public String getShortName() {
return ShortName;
}
public void setShortName(String shortName) {
ShortName = shortName;
}
@Override
public boolean equals(Object obj) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("this " + this.ShortName);
LOGGER.debug("compared " + obj.toString());
}
if (this.ShortName.equals((String)obj)) {
return true;
}
return false;
}
@Override
public String toString() {
return "TestSelect [ShortName=" + ShortName + "]";
}
}