Получение того же экземпляра `componentType` в составном компоненте при каждом использовании - PullRequest
2 голосов
/ 26 июня 2011

Привет, есть странная проблема, в которой я использую Composite Component, который я написал, и я получаю значения от предыдущего использования базового компонента CC (компонент componentType)

Я не знаю, как описать это лучше, чем просто показать код. Я постараюсь быть кратким об этом и вырезать лишние части: Это определение Composite Component:

<cc:interface componentType="dynamicFieldGroupList">
   <cc:attribute name="coupletClass" />
   <cc:attribute name="form" default="@form"/>
   <cc:attribute name="list" type="java.util.List" required="true"/>
   <cc:attribute name="fieldNames" type="java.util.List" required="true" />
</cc:interface>

<cc:implementation>
    <h:dataTable value="#{cc.model}" var="currLine">
        <h:column>
            <h:outputText id="inner_control_component" value="Inner Look at currLine:#{currLine}"/>
        </h:column>
    </h:dataTable>
</cc:implementation>

Определение bean-компонента CC:

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

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

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

        return model;
    }

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

}

И код использования:

<ui:repeat var="group" value="#{currentContact.detailGroups}">
    <h:panelGroup rendered="#{not empty group.values}">
        <h:outputText id="controlMsg" value=" list:#{group.values}" /><br/><br/>
        <utils:fieldTypeGroupList list="#{group.values}"
            fieldNames="#{group.fields}" coupletClass="utils" />
    </h:panelGroup>
</ui:repeat>

Текст идентификатора controlMsg отображает правильные значения в #{group.values}, в то время как управляющий выход внутри компонента идентификатора inner_control_component показывает значения из предыдущего использования.

Значения верны в первый раз ...

Я полагаю, это фундаментальная ошибка при использовании bean-компонента CC, в противном случае это может быть ошибка с MyFaces 2.1 (который я использую)

Ответы [ 2 ]

6 голосов
/ 27 июня 2011

Объяснение этого поведения простое: в представлении определен только один компонент.Так что есть только один компонент поддержки с одной моделью.Поскольку модель загружается при первом получении, одна и та же модель используется повторно в каждой итерации родительского итерирующего компонента.

<ui:repeat> не выполняется во время сборки представления (как JSTL), ново время просмотра время рендеринга.Таким образом, в представлении физически не так много компонентов, как элементов, которые повторяются с помощью <ui:repeat>.Если бы вы использовали <c:forEach> (или любой другой тег итерации, который выполняется во время сборки представления), тогда составной компонент работал бы так, как вы ожидаете.

Вы хотели бы изменить способ, которым модель данныххранится в резервном компоненте.Вы хотите сохранить отдельную модель данных для каждой итерации родительского итеративного компонента.Одним из способов является замена свойства model следующим образом:

private Map<String, DataModel> models = new HashMap<String, DataModel>();

public DataModel getModel() {
    DataModel model = models.get(getClientId());
    if (model == null) {
        model = models.put(getClientId(), new ListDataModel(getList()));
    }
    return model;
}

См. Также:

3 голосов
/ 27 июня 2011

Проблема, описанная здесь, является старой известной из JSF, скрытой за счет использования составных компонентов. Это так важно и так сложно, что вместо ответа здесь я создаю подробный ответ в записи блога для этого: Состояние компонента JSF на строку для таблиц данных

Чтобы этот ответ был коротким, я скажу вам, что это не ошибка в MyFaces 2.1. Пожалуйста, используйте 2.1.1, потому что это версия 2.1.0 для быстрого исправления ошибок. В JSF 2.1 есть новое свойство для h: dataTable, которое называется rowStatePreserved, и этот сценарий является лишь одним из случаев, когда «этот маленький ребенок» становится полезным. Просто замените ui: repeat на h: dataTable и добавьте rowStatePreserved = "true". Это сделает свое дело. Если вам нужно манипулировать моделью (добавлять или удалять строки), вы можете использовать tomahawk t: dataTable и t: dataList, но сейчас вам нужно сделать снимок версии. Обратите внимание, что на данный момент это новый материал, недоступный в любой другой среде JSF (июнь 2011 г.).

Если вам нужна дополнительная информация, следите за обновлениями MyFaces Team в Twitter или обратитесь к экспертам по пользователям MyFaces и спискам рассылки разработчиков .

...