我正在尝试理解如何编写复合组件,并且遵循了balusc和其他人的优秀示例,但我遗漏了一些东西。
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:cc="http://java.sun.com/jsf/composite">
<cc:interface componentType="simpleComponent">
<cc:attribute name="value" required="true" type="example.LanguageDefinition"/>
<cc:attribute name="possibilities" default="de_DE" type="java.lang.String"/>
</cc:interface>
<cc:implementation>
<p:selectOneMenu binding="#{cc.inputComponent}" converter="omnifaces.SelectItemsConverter" var="l"
value="#{cc.attrs.value}">
<p:ajax update="@form"/>
<f:selectItems value="#{cc.languages}" var="l" itemLabel="#{l.label}"
itemValue="#{l}" />
<p:column>#{l.label}</p:column>
<p:column>
<p:graphicImage name="#{l.imgPath}" />
</p:column>
</p:selectOneMenu>
</cc:implementation>
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.faces.component.FacesComponent;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIInput;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
import example.LanguageDefinition;
@FacesComponent("simpleComponent")
public class SimpleComponent extends UIInput implements NamingContainer {
private UIInput inputComponent;
public UIInput getInputComponent() {
return inputComponent;
}
public void setInputComponent(UIInput inputComponent) {
this.inputComponent = inputComponent;
}
@Override
public Object getSubmittedValue() {
return inputComponent.getSubmittedValue();
}
@Override
protected Object getConvertedValue(FacesContext context, Object newSubmittedValue) {
return (String) newSubmittedValue;
}
@Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
String possibilities = getAttributeValue("possibilities", "en_US");
// In theory, build based on incoming possibilities, now hard code
List<LanguageDefinition> languages = new ArrayList<LanguageDefinition>();
languages.add(new LanguageDefinition("pt_PT",
"images/flags/PT.gif", "Português (Portugal)"));
languages.add(new LanguageDefinition("cs_CZ",
"images/flags/CZ.gif", "Czech (Czech Republic)"));
getStateHelper().put("languages", languages);
super.encodeBegin(context);
}
@SuppressWarnings("unchecked")
public List<LanguageDefinition> getLanguages() {
return (List<LanguageDefinition>) getStateHelper().get("languages");
}
/**
* Return specified attribute value or otherwise the specified default if it's null.
*/
@SuppressWarnings("unchecked")
private <T> T getAttributeValue(String key, T defaultValue) {
T value = (T) getAttributes().get(key);
return (value != null) ? value : defaultValue;
}
}
这不能像这样调用:
<ex:simpleComponent value="#{compBean.selected}"/>
一切都很好,但提交的值永远不会传递回我的“compBean”。但是,如果我以任何其他方式设置selectItems“语言”,而不是在encodeBegin中设置它,它可以...作为带有getter和setter的成员变量,或使用此代码:
<c:set target="#{cc}" property="possibilities" value="#{cc.attrs.possibilities}"/>
结合这个更简单的课程:
import java.util.ArrayList;
import java.util.List;
import javax.faces.component.FacesComponent;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIInput;
import javax.faces.component.UINamingContainer;
import example.LanguageDefinition;
@FacesComponent("simpleComponent")
public class SimpleComponent extends UIInput implements NamingContainer {
@Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
public void setPossibilities(String possibilities) {
if (getStateHelper().get("possibilities") == null) {
List<LanguageDefinition> languages = new ArrayList<LanguageDefinition>();
languages.add(new LanguageDefinition("pt_PT",
"images/flags/PT.gif", "Português (Portugal)"));
languages.add(new LanguageDefinition("cs_CZ",
"images/flags/CZ.gif", "Czech (Czech Republic)"));
getStateHelper().put("languages", languages);
getStateHelper().put("possibilities", possibilities);
}
}
public String getPossibilities() {
return (String) getStateHelper().get("possibilities");
}
@SuppressWarnings("unchecked")
public List<LanguageDefinition> getLanguages() {
return (List<LanguageDefinition>) getStateHelper().get("languages");
}
}
但是,这样做是不对的(不是balusc的方式),所以我只是想了解。哪种方式更好?假设第一个,为什么我的不工作?
谢谢!
答案 0 :(得分:1)
所以......这不起作用的原因是因为我忘了在我的自定义下拉列表值对象“example.LanguageDefinition”上实现Serializable。
希望下一个人只要我这样做就不必在大海捞针中寻找此针:)