2013-10-06 41 views
0

我想了解如何对复合组件进行编程,并且已经通过balusc和其他方法跟踪了很好的例子,但我错过了一些东西。为什么我不能在复合组件中的encodeBegin中设置f:selectItems?

<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”。但是,如果我不是在encodeBegin它做其他任何其他方式设置selectItems的“语言”的作品......与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的方式做到了),所以我只是想了解。哪种方法更好?假设第一个,我为什么不工作?

谢谢!

回答

1

所以...这是不工作的原因是因为我忘了在我的自定义下拉列表值对象“example.LanguageDefinition”上实现Serializable。

希望下一个人不必在干草堆里找这根针,只要我做:)

相关问题