1

我試着問一個more specific的問題,但我認爲我可能過於具體,所以我會縮小以獲得更好的建議。 我試圖創建一個複合/自定義組件,將接受兩個屬性如何使用自定義/複合組件執行此操作?

  1. 字符串列表 - >團場與<fieldName, fieldValue> - >字段名
  2. 一個<String, Value>的名單列表

示例值:

  1. [Street, Country, State, ZipCode]
  2. [{(Street, Greenfield), (Country, USA)}, {(Country, Canada), (ZipCode, 3333)}]

該組件將呈現此基礎上,屬性:

enter image description here

我有這個成分困難的原因是,我不知道什麼是保持佔位符的正確方法做用於最初沒有輸入但可以由用戶通過組件添加的字段。

在上例中,對於第一組,這些將是StateZipCode

我的想法是創建一個包含所有字段的虛擬對象,並在提交時將虛擬對象的值複製到在屬性中傳遞的數據結構中。 我面臨的問題是不知道如何讀取組件創建的值並在提交時更改通過屬性傳遞的列表。

我會盡快添加示例代碼(雖然這不應該是回答這個問題的關鍵)

謝謝你只是遠遠閱讀本! :-)

我的代碼(同樣,不需要回答這個問題,但可能有助於理解我的挑戰)

複合組件代碼:

<cc:interface componentType="dynamicFieldList"> 
    <cc:attribute name="styleClass" default="fieldType" /> 
    <cc:attribute name="form" default="@form" 
     shortDescription="If used, this is the name of the form that will get executed" /> 
    <cc:attribute name="list" type="java.util.List" required="true" 
     shortDescription="The values of the list. The type must be List of FieldGroup" /> 
    <cc:attribute name="groupTypes" type="java.util.List" required="true" 
     shortDescription="The types that will be available to choose from for each field. The type of this must be List of FieldType" /> 
</cc:interface> 

<cc:implementation> 
    <h:dataTable id="table" value="#{cc.model}" var="fieldGroup"> 
     <h:column> 
      <ui:repeat var="field" value="#{fieldGroup.values}"> 
       <utils:fieldType value="#{field.value}" type="#{field.type}"/> 
      </ui:repeat> 
     </h:column> 
     <h:column> 
      <h:commandButton value="delete" action="#{cc.remove}"> 
       <f:ajax render="#{cc.attrs.form}" execute="#{cc.attrs.form}" /> 
      </h:commandButton> 
     </h:column> 
    </h:dataTable> 
    <h:commandButton value="add" action="#{cc.add}"> 
     <f:ajax render="#{cc.attrs.form}" execute="#{cc.attrs.form}" /> 
    </h:commandButton> 
</cc:implementation> 

組件豆Java代碼:

@FacesComponent(value = "dynamicFieldGroupList") 
// To be specified in componentType attribute. 
@SuppressWarnings({ "rawtypes", "unchecked" }) 
// We don't care about the actual model item type anyway. 
public class DynamicFieldGroupList extends UIComponentBase implements NamingContainer 
{ 
    private transient DataModel model; 
    private List<FieldGroup> displayList; 

    public DynamicFieldGroupList() 
    { 
     super(); 
     List<FieldGroup> list = new ArrayList<FieldGroup>(); 

     for (FieldGroup group : getList()){ 
      FieldGroup currGroup = new FieldGroup("Untitled"); 

      //Assumption - Each type may exist only once in a group. 
      Map<FieldType, FieldDetail> hash = new HashMap<FieldType, FieldDetail>(); 

      for (FieldDetail detail: group.getDetails()){ 
       hash.put(detail.getType(), detail); 
      } 

      // While creating the dummy object, insert values the exist or placeholders if they don't. 
      for (FieldType type : getGroupTypes()){ 
       if (hash.containsKey(type)){ 
        currGroup.addDetail(hash.get(type)); 
       } else { 
        currGroup.addDetail(new FieldDetail(type,null)); 
       } 
      } 

      list.add(currGroup); 
     } 

     // Assign the created list to be the displayed (dummy) object 
     setDisplayList(list); 
    } 

    public void add() 
    { 
     // Add a new group of placeholders 
     FieldGroup group = new FieldGroup("Untitled"); 

     for (FieldType type: getGroupTypes()){ 
      group.addDetail(new FieldDetail(type, null)); 
     } 

     getList().add(group); 
    } 

    public void remove() 
    { 
     getDisplayList().remove(model.getRowData()); 
    } 

    @Override 
    public String getFamily() 
    { 
     return "javax.faces.NamingContainer"; // Important! Required for 
               // composite components. 
    } 

    public DataModel getModel() 
    { 
     if (model == null) 
      model = new ListDataModel(getDisplayList()); 
     return model; 
    } 

    private List<FieldGroup> getList() 
    { // Don't make this method public! Ends otherwise in an infinite loop 
     // calling itself everytime. 
     return (List) getAttributes().get("list"); 
    } 

    private List<FieldType> getGroupTypes() 
    { // Don't make this method public! Ends otherwise in an infinite loop 
     // calling itself everytime. 
     return (List) getAttributes().get("groupTypes"); 
    } 

    public void setDisplayList(List<FieldGroup> displayList) 
    { 
     this.displayList = displayList; 
    } 

    public List<FieldGroup> getDisplayList() 
    { 
     return displayList; 
    } 

} 

回答

2

您可以使用Map來保存每個組的值。

Map<String, Object> values = new HashMap<String, Object>(); 

假設你已經在List<Map<String, Object>>和字段名所有這些地圖在List<String>,那麼你就可以獲取/設置他們都基本上如下

<ui:repeat value="#{allValues}" var="values"> 
    <ui:repeat value="#{fieldNames}" var="fieldName"> 
     <h:outputLabel value="#{fieldName}" /> 
     <h:inputText value="#{values[fieldName]}" /> 
     <br/> 
    </ui:repeat> 
</ui:repeat> 
+2

我愛你怎麼來了一個解決方案,使我的代碼大部分冗餘:-) – Ben

+0

不客氣:) – BalusC