PrimeFaces DataTable - 提交表单时视图中的选择设置为 null 并且表本身不在表单中
编辑:根据 Jasper 的评论,选择功能要求 p:dataTable 处于表单中,所以我的问题没有实际意义。
我在表单之外有一个数据表。当我提交表单(非 ajax)时,选择属性引用的字段在我的视图中设置为 null。 PrimeFaces 10.0.1 及更高版本会发生这种情况。在 10.0.0 和 8.x 中,该字段未被触及。
示例中的字段是DtView.selectedEntry
。
xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>PrimeFaces Test</title>
</h:head>
<h:body>
<p:dataTable id="data-table" var="entry"
value="#{dtView.entries}"
rowKey="#{entry.id}"
selection="#{dtView.selectedEntry}"
selectionMode="single">
<p:column headerText="Entry">
<h:outputText value="#{entry}" />
</p:column>
</p:dataTable>
<h:form id="frmTest">
<div>
<p:outputLabel for="@next" value="Selected: "/>
<h:outputText id="selected-entry" value="#{dtView.selectedEntry}" />
</div>
<div>
<p:commandButton value="save input"
ajax="false"
imediate="true"
update="@form :data-table"
action="#{dtView.submit()}" />
</div>
</h:form>
</h:body>
</html>
视图:
@Data
@Named
@ViewScoped
public class DtView implements Serializable {
private List<Product> entries;
private Product selectedEntry;
@PostConstruct
void setup() {
entries = List.of(
new Product(1, "entry 1"),
new Product(2, "entry 2"),
new Product(3, "entry 3")
);
selectedEntry = entries.get(0);
}
public String submit() {
System.out.println("Selected entry: " + selectedEntry);
return null;
}
}
控制台(PrimeFaces 11.0.0 和 10.0.0):
Selected entry: null
Selected entry: Product(id=1, name=entry 1)
为了避免“null”,我可以将 p:dataTable 放入表单中,这样它就不会在应用请求值阶段或使用 ajax 进行处理命令按钮。我不确定为什么数据表在我的实际应用程序中的表单之外。
我期望不在视图中设置表单之外的值,但 dataTable 似乎不遵循这一点。新的PF行为是否更符合逻辑,而我的理解是错误的?
这一变化的原因似乎位于 SelectionFeature 中。
PF 8:只需调用 table.setSelection(null);
: https://github.com/primefaces/primefaces/blob/cd4fbdf1d9d4ae054da19b9a84001d0c34d142eb/src/main/java/org/primefaces/component/datatable/feature/SelectionFeature.java#L78
PF 10.0.0: decodeSingleSelection()
不会调用 setSelection()
,因为 !rowKeys.isEmpty()
计算结果为 false
(空检查在 10.0.1 中消失): https://github.com/primefaces/primefaces/blob/10.0.0/src/main/java/org/primefaces/component/datatable/feature/SelectionFeature.java#L84
11.0.0: decodeSingleSelection()
最终调用 setSelection()
将视图中的值设置为 null: https://github.com/primefaces/primefaces/blob/11.0.0/primefaces/src/main/java/org/primefaces/component/datatable/feature/SelectionFeature.java#L87
edit: Based on Jasper's comment, the selection feature requires p:dataTable to be in a form, so my question is moot.
I have a DataTable outside of a form. When I submit the form (non-ajax), the field referenced by the selection attribute is set to null in my view. This happens for PrimeFaces 10.0.1 and higher. In 10.0.0 and 8.x, the field is not touched.
The field in the example is DtView.selectedEntry
.
xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>PrimeFaces Test</title>
</h:head>
<h:body>
<p:dataTable id="data-table" var="entry"
value="#{dtView.entries}"
rowKey="#{entry.id}"
selection="#{dtView.selectedEntry}"
selectionMode="single">
<p:column headerText="Entry">
<h:outputText value="#{entry}" />
</p:column>
</p:dataTable>
<h:form id="frmTest">
<div>
<p:outputLabel for="@next" value="Selected: "/>
<h:outputText id="selected-entry" value="#{dtView.selectedEntry}" />
</div>
<div>
<p:commandButton value="save input"
ajax="false"
imediate="true"
update="@form :data-table"
action="#{dtView.submit()}" />
</div>
</h:form>
</h:body>
</html>
View:
@Data
@Named
@ViewScoped
public class DtView implements Serializable {
private List<Product> entries;
private Product selectedEntry;
@PostConstruct
void setup() {
entries = List.of(
new Product(1, "entry 1"),
new Product(2, "entry 2"),
new Product(3, "entry 3")
);
selectedEntry = entries.get(0);
}
public String submit() {
System.out.println("Selected entry: " + selectedEntry);
return null;
}
}
Console (PrimeFaces 11.0.0 and then 10.0.0):
Selected entry: null
Selected entry: Product(id=1, name=entry 1)
To avoid the 'null' I can put p:dataTable inside a form, so it won't get processed during the apply request value phase or use ajax on the command button. I am not sure why the dataTable is outside a form in my real application to begin with.
I expected a value outside of a form not to be set in the view, but dataTable does not seem to follow this. Is the new PF behaviour more logical and my understanding is wrong?
The reason for this change seems to be located in SelectionFeature.
PF 8: just calls table.setSelection(null);
:
https://github.com/primefaces/primefaces/blob/cd4fbdf1d9d4ae054da19b9a84001d0c34d142eb/src/main/java/org/primefaces/component/datatable/feature/SelectionFeature.java#L78
PF 10.0.0: decodeSingleSelection()
does not call setSelection()
because !rowKeys.isEmpty()
evaluates to false
(empty check disappears in 10.0.1):
https://github.com/primefaces/primefaces/blob/10.0.0/src/main/java/org/primefaces/component/datatable/feature/SelectionFeature.java#L84
11.0.0: decodeSingleSelection()
eventually calls setSelection()
to set the value in the view to null:
https://github.com/primefaces/primefaces/blob/11.0.0/primefaces/src/main/java/org/primefaces/component/datatable/feature/SelectionFeature.java#L87
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论