[英]How to update button inside <ui: repeat>?
这是我的问题。 我在<ui: repeat>
中有两个<p: commandLink>
> 。 当我单击它们时,我需要通过模拟复选框来更新这些按钮。 围绕<ui:repeat>
更新<panelGroup>
> 有效。 但是对于一个包含许多项目的列表,在单击更新按钮后,它会使屏幕 go 回到列表顶部,这使得 select 许多项目变得不切实际。 有没有办法在<p:commandLink>
中给出更新特定行?
<tbody>
<ui:repeat value="#{myBean.itens}" var="item" varStatus="index">
<tr class="myCustomClass" id="item#{item.id}">
<th>
<p:commandLink
rendered="#{myConditionRendered}"
actionListener="#{myBean.deselect(item)}"
update=":panelGroupArroundId"
process="@this">
<i style="font-size: 15px;" class="fa fa-check-square-o" />
</p:commandLink>
<p:commandLink
rendered="#{!myConditionRendered}"
actionListener="#{myBean.select(item)}"
update=":panelGroupArroundId"
process="@this">
<i style="font-size: 15px;" class="fa fa-square-o" />
</p:commandLink>
</th>
<td>
<h:outputText value="#{item.field1}"/>
</td>
...
</tr>
</ui:repeat>
</tbody>
JSF 版本:2.1
Primefaces 版本:3.5
这里的技巧是只更新您需要的部分 - 如果您更新整个容器,浏览器将从最近更新发生的位置重置和刷新。 在 JSF 中,有几种方法可以完成您的需要。 更新版本的 JSF(尤其是 2.3)具有可用的选择器,例如:parent
,以便更轻松地针对页面的特定部分进行更新。 使用 2.1,您会受到更多限制。
我进行了快速测试,并提出了您特定用户案例的工作示例。 下图使用 Font Awesome 和 PrimeFaces 3.5;
我稍微调整了您的代码并制作了一个完整且有效的示例。 在此示例中,controller 和 backing bean 已分离到单独的类中。 首先让我们看一下backing bean:
@Data @Named @ViewScoped
public class MyBean implements Serializable {
@Data @RequiredArgsConstructor
public static class Item {
@NonNull private String name;
private boolean selected;
}
private List<Item> items;
@PostConstruct
private void init() {
items = List.of(new Item("a"), new Item("b"), new Item("c"),
new Item("d"), new Item("e"), new Item("f"), new Item("g"),
new Item("h"), new Item("i"), new Item("j")
);
}
}
这定义了我们的数据集并使用 Lombok 来最小化样板代码的数量( @Data
和@RequiredArgsConstructor
)。 我还添加了一个 selected 标志来跟踪复选框是否被选中。 然后在选择和取消选择时在 controller bean 中使用:
@Data @Named @RequestScoped
public class MyBeanController {
@Inject
private MyBean myBean;
public void select(Item item) {
item.setSelected(true);
}
public void deselect(Item item) {
item.setSelected(false);
}
}
此外,这里是视图 (XHTML) 定义:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Button update in UI repeat example</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.0.0/css/font-awesome.css" />
</h:head>
<h:body>
<table>
<tbody>
<ui:repeat value="#{myBean.items}" var="item">
<tr style="float: left; padding-right: 10px">
<th>
<h:form>
<h:panelGroup id="content">
<p:commandLink rendered="#{item.selected}"
actionListener="#{myBeanController.deselect(item)}"
update="content" process="@this">
<i class="fa fa-check-square-o" />
</p:commandLink>
<p:commandLink rendered="#{!item.selected}"
actionListener="#{myBeanController.select(item)}"
update="content" process="@this">
<i class="fa fa-square-o" />
</p:commandLink>
</h:panelGroup>
</h:form>
</th>
<td><h:outputText value="#{item.name}"/></td>
</tr>
</ui:repeat>
</tbody>
</table>
</h:body>
</html>
如您所见,我们将按钮包装在表单中并定义了我们在p:commandLink
标记的update
属性中引用的容器content
。 因为我们被包裹在一个表单中,所以 panelGroup 的实际 id 实际上变成了类似于j_idt6:9:j_idt8:content
的东西,每个content
id 都是唯一的(因为每个表单都有一个唯一的 id 生成)。
这使我们能够专门针对和更新该行的数据。
从理论上讲,您可以直接update
表单,而无需将其包装在content
中。 但是,当包裹在ui:repeat
中时,这样做会干扰表单的生命周期和处理。 添加一个额外的panelGroup
并更新它,就像在这个例子中一样,解决了这个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.