在Core JavaServer Faces中,我们找到以下用于从DataTable中删除行的示例,其中tableData.names是Name对象的列表:
<h:dataTable value="#{tableData.names}" var="name" ... />
<h:commandLink value="Delete" action="#{tableData.deleteRow(name)}" />
</h:dataTable>
它附带一个警告,如果我们使用请求范围并且列表在“表的呈现和响应的解码之间”之间发生更改,则可能不会删除正确的行。
注意:如果数据表的值具有请求范围,请确保数据在表的呈现和响应的解码之间不会发生变化 (第3版第226页)
任何人都可以根据JSF生命周期来解释这个引用吗?如果“渲染响应”是JSF生命周期的最后阶段,那么“解码响应”适合哪里?它们是否意味着解码以下回发REQUEST(它发送生成的ID来识别行,从而识别名称对象)?
并且:我们如何以更强大的方式实现这一点?
答案 0 :(得分:2)
在显示表单的请求期间(在书正在讨论的编码步骤)期间不评估方法表达式,但是在处理表单提交的请求期间(本书所讨论的解码步骤)。数据表行的输入和操作是根据表的行索引确定的。在处理表单提交期间,JSF重新遍历数据模型,以便查找提交的值和调用的操作。
因此,如果<h:dataTable value>
与请求范围的bean相关联,因此基于每个请求重新初始化数据模型,那么您将冒#{item}
实际< / em>在处理表单提交期间引用错误索引处的项目,因为在显示表单和提交表单的请求之间,数据库可能已检索到新项目,或已删除了另一项可能会移动期望的项目到不同的索引。
为了避免这种情况,需要将bean放在视图范围中,以便在回发中保留在初始请求的(post)构造函数中初始化的完全相同的datamodel,而无需在开始时重新初始化它。每个请求,因此可能包含不同的项目或不同的顺序。如果在完全控制最终用户(如搜索查询)的情况下将数据模型的加载与特定请求参数绑定,则影响会更大。
另一种选择,在这个特殊的非幂等“删除此项目”案例中实际上是一个不好的选择,但对于幂等“编辑此项目”案例来说,这是一个很好的选择,而是使用GET链接。所需项目立即呈现为<a>
元素的查询字符串参数。
<h:link value="Edit" outcome="edit">
<f:param name="id" value="#{item.id}" />
</h:link>