1

もっと具体的な質問をしようとしましたが、あまりにも具体的だったのではないかと思いますので、ズームアウトしてより良いアドバイスをもらいます。2つの属性を受け入れるコンポジット/カスタムコンポーネントを作成しようとしています

  1. 文字列のリスト->フィールドの名前
  2. <String, Value>->フィールドのグループのリストのリスト<fieldName, fieldValue>

値の例:

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

コンポーネントは、属性に基づいてこれをレンダリングします。

ここに画像の説明を入力してください

このコンポーネントで問題が発生する理由は、元々入力されていないが、コンポーネントを介してユーザーが追加できるフィールドのプレースホルダーを維持するための適切な方法がわからないためです。

上記の例では、最初のセットの場合、これらはとにStateなりZipCodeます。

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

すぐにサンプルコードを追加します(ただし、この質問に答えるのに重要なことではありません)

ここまで読んでくれてありがとう!:-)

私のコード(繰り返しますが、質問に答えるのに必要ではありませんが、私の挑戦を理解するのに役立つかもしれません)

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

<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>

コンポーネントBeanの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;
    }

}
4

1 に答える 1

2

を使用しMapて、各グループの値を保持できます。

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

List<Map<String, Object>>これらすべてのマップがaにあり、フィールド名がにあると仮定すると、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>
于 2011-06-23T08:19:29.997 に答える