我有一个迭代列表的数据表,我们称之为myList。我根据一些请求参数填充此myList。在数据表中有commandLinks。如果我在应用请求值阶段将一个虚拟条目放入myList,我可以单击第一个commandLink,它可以正常工作(它在调用应用程序阶段执行,然后正确的条目在myList中)。如果我不这样做,或者我点击第二个或更高版本的commandLink,没有任何反应。因此,我猜测命令按钮的clientId在应用请求阶段被解析,甚至认为它仅在调用应用程序阶段使用,这导致命令链接断开。
类似的东西:
<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来存储数据。
答案 0 :(得分:0)
在应用请求值阶段,JSF需要遍历模型以查找单击的命令链接。如果在HTTP请求期间模型更改不兼容,其中表单提交被处理(回发),与初始HTTP请求相比,其中显示了带有命令链接的表,则JSF可能无法找到单击的命令链接,因此永远不会对所需的操作进行排队,或者表示“当前行”的对象与最终用户的意图不同。
如果您的bean是请求作用域,那么它应该以这样的方式编写,即它在构造函数或基于某个请求参数的selectedTest
方法中初始化@PostConstruct
。至少是you should absolutely not perform business logic in getters。
您可以在命令链接中传递将selectedTest
重建为<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!
答案 1 :(得分: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>