Primefaces 的 commandLink 仅适用于数据表的第一页
Primefaces' commandLink works only on the first page of a dataTable
我在 p:dataTable 中有一个包含 p:commandLink 的列,它有一个分页器。当用户单击 commandLink 时,将打开一个对话框,显示该行的数据。
数据表html代码:
<p:dataTable id="dtSample" value="#{sessionBean.sampleList}"
binding="#{requestBean.dtSampleList}"
paginator="true" paginatorPosition="bottom"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="#{10,25,50}"
currentPageReportTemplate="({startRecord} of {totalRecords})"
var="item" emptyMessage="No entries." rows="10" rowKey="#{item.id}">
<p:column headerText="Id">
<p:commandLink id="lnkSample"
action="#{requestBean.onLinkClick(item)}"
oncomplete="PF('dlgSample').show();"
update="@(.dialogClass)">
<h:outputText value="#{item.id}" />
</p:commandLink>
</p:column>
<p:column headerText="Code">
<h:outputText value="#{item.code}" />
</p:column>
<p:column headerText="Description">
<h:outputText value="#{item.descr}" />
</p:column>
</p:dataTable>
请求bean:
public class RequestBean {
private SessionBean sessionBean;
private DataTable dtSampleList;
public void init() {
// load samle list
loadSampleList();
}
public String onLinkClick(Sample sample) {
getSessionBean().setSelectedSample(sample);
return "success";
}
private void loadSampleList() {
List<Sample> list = new ArrayList<Sample>();
for (int i = 0; i < 100; i++) {
Sample tmp = new Sample();
tmp.setId(new BigDecimal(i + 1));
tmp.setCode("code" + (i + 1));
tmp.setDescr("desc" + (i + 1));
list.add(tmp);
}
getSessionBean().setSampleList(list);
}
// getters and setters
}
会话 bean:
public class SessionBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<Sample> sampleList;
private Sample selectedSample;
// getters and setters
}
对话html代码:
<p:dialog id="dlgSample" closeOnEscape="true" widgetVar="dlgSample"
styleClass="dialogClass" modal="true">
<p:panelGrid columns="1">
<h:outputText value="Id: #{sessionBean.selectedSample.id}" />
<h:outputText value="Code: #{sessionBean.selectedSample.code}" />
<h:outputText value="Description: #{sessionBean.selectedSample.descr}" />
</p:panelGrid>
</p:dialog>
当我单击数据表第一页上的 link 时,会执行 link 操作并正确刷新显示行数据的对话框。但是当我移动到数据表的以下任何页面时,单击 link 不会刷新对话框中的数据(未调用 link 操作,因此对话框中的数据是错误的- selectedSample
变量有旧值)。当然,当我回到数据表的第一页时,命令 link 再次起作用(调用操作方法并刷新数据)。
我做错了什么?为什么没有在任何数据表页面上调用操作方法?
我正在使用 Primefaces 5.2。
What am I doing wrong? Why is action method not called on any datatable page?
导致该行为的一个常见错误是您的 state
不一致:为了处理表单提交,JSF 将重新创建与先前请求中完全相同的视图,然后应用更改(执行动作)
如果这个新视图现在与提交之前的视图不同,则每个操作都会中止并且不会被调用。 (涉及的元素不同。即,如果您的 commandLink 在提交前是 rendered="true"
,则在 APPLY_REQUEST_VALUES
-Phase 期间它需要是 rendered="true"
)。
因此,根据您的描述,我假设您的 table 正在 回落 到第 1 页,这将删除第 2 页上的所有 link从视图并中止它的视图操作,因为元素不再 rendered.
出于同样的原因,第 1 页上的 links 正在运行,因为即使您的 table 失去对当前页面的跟踪 - 它也会呈现第 1 页,因此您有相同的视图和以前一样,所以提交有效。
您可以轻松地验证这一点,方法是增加每页的元素数量并查看从第 2 页移至第 1 页的每个 link 现在都在工作。
但是在没有看到整个 bean 的情况下,我只能这样假设。为了便于测试,将您的 bean 设置为 @SessionScoped
并查看是否可以解决问题。
有关更多想法,请参阅此 post:commandButton/commandLink/ajax action/listener method not invoked or input value not updated
将 p:commandLink 等组件放在 p:dataTable 行中时,您应始终指定
process="@this"
所以,对于你的情况,我会尝试:
<p:commandLink id="lnkSample"
action="#{bean.onLinkClick(item)}"
oncomplete="PF('dlgSample').show();"
update="@(.dialogClass)">
<h:outputText value="#{item.id}" />
</p:commandLink>
这样做,你确定只会处理link上的点击,不会执行其他提交。
看起来问题出在 PF dataTable 组件中。缺少 first
和 rows
属性,添加它们后,所有页面上的命令链接都按预期工作。
我在 p:dataTable 中有一个包含 p:commandLink 的列,它有一个分页器。当用户单击 commandLink 时,将打开一个对话框,显示该行的数据。
数据表html代码:
<p:dataTable id="dtSample" value="#{sessionBean.sampleList}"
binding="#{requestBean.dtSampleList}"
paginator="true" paginatorPosition="bottom"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="#{10,25,50}"
currentPageReportTemplate="({startRecord} of {totalRecords})"
var="item" emptyMessage="No entries." rows="10" rowKey="#{item.id}">
<p:column headerText="Id">
<p:commandLink id="lnkSample"
action="#{requestBean.onLinkClick(item)}"
oncomplete="PF('dlgSample').show();"
update="@(.dialogClass)">
<h:outputText value="#{item.id}" />
</p:commandLink>
</p:column>
<p:column headerText="Code">
<h:outputText value="#{item.code}" />
</p:column>
<p:column headerText="Description">
<h:outputText value="#{item.descr}" />
</p:column>
</p:dataTable>
请求bean:
public class RequestBean {
private SessionBean sessionBean;
private DataTable dtSampleList;
public void init() {
// load samle list
loadSampleList();
}
public String onLinkClick(Sample sample) {
getSessionBean().setSelectedSample(sample);
return "success";
}
private void loadSampleList() {
List<Sample> list = new ArrayList<Sample>();
for (int i = 0; i < 100; i++) {
Sample tmp = new Sample();
tmp.setId(new BigDecimal(i + 1));
tmp.setCode("code" + (i + 1));
tmp.setDescr("desc" + (i + 1));
list.add(tmp);
}
getSessionBean().setSampleList(list);
}
// getters and setters
}
会话 bean:
public class SessionBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<Sample> sampleList;
private Sample selectedSample;
// getters and setters
}
对话html代码:
<p:dialog id="dlgSample" closeOnEscape="true" widgetVar="dlgSample"
styleClass="dialogClass" modal="true">
<p:panelGrid columns="1">
<h:outputText value="Id: #{sessionBean.selectedSample.id}" />
<h:outputText value="Code: #{sessionBean.selectedSample.code}" />
<h:outputText value="Description: #{sessionBean.selectedSample.descr}" />
</p:panelGrid>
</p:dialog>
当我单击数据表第一页上的 link 时,会执行 link 操作并正确刷新显示行数据的对话框。但是当我移动到数据表的以下任何页面时,单击 link 不会刷新对话框中的数据(未调用 link 操作,因此对话框中的数据是错误的- selectedSample
变量有旧值)。当然,当我回到数据表的第一页时,命令 link 再次起作用(调用操作方法并刷新数据)。
我做错了什么?为什么没有在任何数据表页面上调用操作方法?
我正在使用 Primefaces 5.2。
What am I doing wrong? Why is action method not called on any datatable page?
导致该行为的一个常见错误是您的 state
不一致:为了处理表单提交,JSF 将重新创建与先前请求中完全相同的视图,然后应用更改(执行动作)
如果这个新视图现在与提交之前的视图不同,则每个操作都会中止并且不会被调用。 (涉及的元素不同。即,如果您的 commandLink 在提交前是 rendered="true"
,则在 APPLY_REQUEST_VALUES
-Phase 期间它需要是 rendered="true"
)。
因此,根据您的描述,我假设您的 table 正在 回落 到第 1 页,这将删除第 2 页上的所有 link从视图并中止它的视图操作,因为元素不再 rendered.
出于同样的原因,第 1 页上的 links 正在运行,因为即使您的 table 失去对当前页面的跟踪 - 它也会呈现第 1 页,因此您有相同的视图和以前一样,所以提交有效。
您可以轻松地验证这一点,方法是增加每页的元素数量并查看从第 2 页移至第 1 页的每个 link 现在都在工作。
但是在没有看到整个 bean 的情况下,我只能这样假设。为了便于测试,将您的 bean 设置为 @SessionScoped
并查看是否可以解决问题。
有关更多想法,请参阅此 post:commandButton/commandLink/ajax action/listener method not invoked or input value not updated
将 p:commandLink 等组件放在 p:dataTable 行中时,您应始终指定
process="@this"
所以,对于你的情况,我会尝试:
<p:commandLink id="lnkSample"
action="#{bean.onLinkClick(item)}"
oncomplete="PF('dlgSample').show();"
update="@(.dialogClass)">
<h:outputText value="#{item.id}" />
</p:commandLink>
这样做,你确定只会处理link上的点击,不会执行其他提交。
看起来问题出在 PF dataTable 组件中。缺少 first
和 rows
属性,添加它们后,所有页面上的命令链接都按预期工作。