JSF h:即使使用f:ajax,也永远不会设置selectOneMenu

时间:2013-06-10 18:50:20

标签: jsf binding

我想在JSF Web应用程序中实现过滤工具,如下所示:用户可以根据需要添加任意数量的过滤器。他们也可以删除它们。所以我有一个dataTable过滤器。每行包含一个h:selectOneMenu,它具有ajax“change”事件,以便在同一行中显示第二个h:selectOneMenu。第二个h:selectOneMenu的选项是根据第一个选择的选项动态计算的。

问题是第二个h:selectOneMenu的值永远不会设置为后端对象,即使我添加了一个ajax事件。但是,第一个h:selectOneMenu的值已设置。

我在.xhtml页面中有以下代码片段:

<h:form id="filterForm">
    <h:dataTable id="filterTable" value="#{filterManager.filters}" var="filter">
        <h:column>
            <h:outputLabel value="#{msgs.filterBy}:" for="availableFilters" />
            <h:selectOneMenu id="availableFilters" value="#{filter.filter}">
                <f:selectItems value="#{filterManager.getProperties(typeSelector.typeSelected)}" />
                <f:ajax event="change" render=":filterForm" />
            </h:selectOneMenu>
        </h:column>

        <h:column>
            <h:panelGroup id="filterValuesPanel" >
                <h:outputLabel value="#{msgs.value}:" for="filterValues" rendered="#{!filter.filterEmpty}" />
                <h:selectOneMenu value="#{filter.value}" id="filterValues" rendered="#{!filter.filterEmpty}" >
                    <f:selectItems value="#{filterManager.getPossibleAnswers(filter)}" />
                    <f:ajax event="change" render=":filterForm" />
                </h:selectOneMenu>
            </h:panelGroup>
        </h:column>

        <h:column>
            <h:commandButton value="#{msgs.delete}" title="#{msgs.deleteFilter}">
                <f:ajax event="click" listener="#{filterManager.removeFilter(filter)}" render=":filterForm" />
            </h:commandButton>
        </h:column>

    </h:dataTable>

    <h:commandButton value="#{msgs.addNewFilter}">
        <f:ajax event="click" listener="#{filterManager.addNewFilter}" render=":filterForm" />
    </h:commandButton>
</h:form>

我有一个名为“FilterManager”的bean,它有一个ViewScoped。重要部分如下所示:

@ManagedBean
@ViewScoped
public class FilterManager implements Serializable {

    private List<Filter> filters; // it has a getter
    private int currentFilterId;

    public void addNewFilter(AjaxBehaviorEvent event) {
        this.currentFilterId++;
        this.filters.add(Filter.getEmptyFilter(this.currentFilterId));
    }

    public void removeFilter(Filter filter) {
        this.filters.remove(filter);
    }

...

}

Filter类是普通类(不是bean),如下所示:

public class Filter implements Serializable {

    private int id;       
    private String filter;
    private String value;


    public String getFilter() {
        return filter;
    }


    public void setFilter(String theFilter) {
        if (theFilter != null && !theFilter.isEmpty())
            this.filter = theFilter;
    }

    public String getValue() {
        return value;
    }


    public void setValue(String theValue) {
        this.value = theValue;
    }

    public boolean isFilterEmpty() {
        return this.filter == null || this.filter.isEmpty();
    }
...

}

请注意,TypeSelector是一个SessionScoped bean,它具有typeSelected属性以及getter和setter。

问题是:filter.filter设置正确,而filter.value从未设置。我找不到问题,所以我需要你的帮助。对所有这些代码表示歉意,但我需要向您提供所有必要的详细信息。

提前致谢!

1 个答案:

答案 0 :(得分:0)

好的家伙那是我的错。我在FilterManager.getPossibleAnswers(过滤器过滤器)方法中有一个错误。基本上,在方法的最后,我无条件地将filter.value设置为List的第一个元素。例如,而不是写

if (filter.getValue() == null || filter.getValue().isEmpty()) {
    SelectItem first = answers.get(0);
    filter.setValue((String) first.getValue());
} 

我刚刚写道:

    SelectItem first = answers.get(0);
    filter.setValue((String) first.getValue());

尽管filter.value正常更新,但在重新呈现dataTable组件期间,值仍会更改回默认值(列表中的第一个元素)。