-1

我有一个遍历列表的数据表,我们称之为 myList。我根据一些请求参数填充了这个 myList。在数据表里面有commandLinks。如果我在应用请求值阶段将一个虚拟条目放入 myList,我可以单击第一个 commandLink,它会正常工作(它在调用应用程序阶段执行,然后正确的条目在 myList 中)。如果我不这样做,或者我单击第二个或以后的 commandLink,则不会发生任何事情。所以我猜测命令按钮的clientId是在应用请求阶段解决的,即使它只在调用应用程序阶段使用,这会导致commandLinks损坏。

像这样的东西:

<h:selectManyCheckbox styleClass="hidden" 
                      value="#{cc.attrs.selectionList.selected}"
                      converter="#{cc.attrs.converter}" >
    <f:selectItems value="#{cc.attrs.selectionList.all}"
                   var="item" itemValue="#{item}" itemLabel="" />
</h:selectManyCheckbox>
<h:dataTable value="#{cc.attrs.selectionList.selectedTest}" var="item">
    <h:column>
        <h:commandLink value="deselect" action="#{cc.attrs.selectionList.deSelect(item)}">
            <f:ajax execute=":#{component.parent.parent.parent.clientId}"
                    render=":#{component.parent.parent.parent.clientId}" />
        </h:commandLink>
    </h:column>
</h:dataTable>

和模型:

public List<E> getSelected()
{
    return myList;
}

public List<E> getSelectedTest()
{
    if(FacesContext.getCurrentInstance().getCurrentPhaseId().equals(PhaseId.RESTORE_VIEW) && getSelectedList().isEmpty())
    {
        return Collections.singletonList(myList.get(0));
    }
    else if(FacesContext.getCurrentInstance().getCurrentPhaseId().equals(PhaseId.APPLY_REQUEST_VALUES) && getSelectedList().isEmpty())
    {
        return Collections.nCopies(2, myList.get(0));
    }
    else if(FacesContext.getCurrentInstance().getCurrentPhaseId().equals(PhaseId.PROCESS_VALIDATIONS) && getSelectedList().isEmpty())
    {
        return Collections.nCopies(3, myList.get(0));
    }
    else if(FacesContext.getCurrentInstance().getCurrentPhaseId().equals(PhaseId.UPDATE_MODEL_VALUES) && getSelectedList().isEmpty())
    {
        return Collections.nCopies(4, myList.get(0));
    }

    return myList;
}

public void deSelect(E item)
{
    myList.remove(item);
}

在此示例中,数据表的前两个 commandLink 有效。我的问题是为什么会出现这种行为,有没有办法不用虚拟条目填充 myList ?我不想使用任何(viewscoped)支持 bean 来存储数据。

4

2 回答 2

0

在应用请求值阶段,JSF 需要遍历模型以找到单击的命令链接。如果与显示带有命令链接的表的初始 HTTP 请求相比,在处理表单提交(回发)的 HTTP 请求期间模型更改不兼容,则 JSF 可能无法找到单击的命令链接,因此永远不要将所需的操作排队,或者表示“当前行”的对象与最终用户的意图不同。

如果您的 bean 是请求范围的,那么它应该以这样的方式编写,即它基于某些请求参数selectedTest在构造函数或方法中初始化。@PostConstruct至少,您绝对不应该在 getters 中执行业务逻辑

您可以在命令链接中传递重建selectedTestas所需的参数。<f:param>

<h:commandLink ...>
    <f:param name="some" value="#{bean.some}" />
</h:commandLink>

并准备模型如下:

@ManagedProperty
private String some;

@PostConstruct
public void init(){ 
    selectedTest = populateItBasedOn(some);
}

// Don't change standard getters/setters!

也可以看看:

于 2013-01-20T01:32:22.463 回答
0

我设法通过将 selectManyCheckbox 本身绑定到我的 componentBindings HashMap 并将其用于 dataTable(在 selectManyCheckbox 上使用 immediate="true")来解决问题:

<h:selectManyCheckbox immediate="true" styleClass="hidden" 
                      binding="#{componentBindings[cc.attrs.selectionList]}"
                      value="#{cc.attrs.selectionList.selected}"
                      converter="#{cc.attrs.converter}" >
    <f:selectItems value="#{cc.attrs.selectionList.all}" var="item"
                   itemValue="#{item}" itemLabel="" />
</h:selectManyCheckbox>

<h:dataTable value="#{componentBindings[cc.attrs.selectionList].value}" var="item">
    <h:column>
        <h:commandLink value="deselect" action="#{cc.attrs.selectionList.deSelect(item)}">
            <f:ajax execute=":#{component.parent.parent.parent.clientId}"
                    render=":#{component.parent.parent.parent.clientId}" />
        </h:commandLink>
    </h:column>
</h:dataTable>

在 faces-config.xml 中:

<managed-bean>
    <description>Holder of all component bindings.</description>
    <managed-bean-name>componentBindings</managed-bean-name>
    <managed-bean-class>java.util.HashMap</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>
于 2013-01-20T07:20:28.563 回答