1

私はmore specificの質問をしましたが、私はあまりにも具体的なので、より良いアドバイスを得るためにズームアウトします。 私は2つの属性カスタム/複合コンポーネントでこれを行うにはどうすればよいですか?

  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になります。

私の考えは、すべてのフィールドを持つダミーオブジェクトを作成し、ダミーオブジェクトの値を属性で渡されたデータ構造にコピーしてコピーすることでした。 私が直面していた問題は、コンポーネントの作成時に値を読み取る方法と、送信時に属性を通過するListを変更する方法を知らないことでした。

(つまり、この質問に答えるために重要ではないはずですが)私は

だけでここまで読んでいただきありがとうございます、すぐにサンプルコードを追加します! :-)

マイコード(再度、質問に答えるために必要ですが、私の挑戦を理解するのに役立つかもしれない)

複合コンポーネントコード:

<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<String>List<Map<String, Object>>とフィールド名のすべてのそれらのマップをしたと仮定すると、あなたが/取得することができます

<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

関連する問題