jsf - 在没有 JavaScript 的情况下动态设置数据列表中的 ID
问题描述
我的 Primefaces 界面有一个大问题。我想对列表进行循环并显示一些信息+隐藏的编辑字段。
XHTML Primefaces 代码片段:
<p:dataList value="#{datas}" var="data">
<div class="ui-g">
<div class="ui-g-3">
<h2>#{data.desc}</h2>
</div>
<div class="ui-g-3">
<p:commandButton operation="edit" disabled="#{data.isLocked()}" actionListener="#{view.edit(data)}"
style="width:120px;" update="edit_#{data.id}" />
<p:commandButton operation="delete" actionListener="#{view.delete(data.getId())}" disabled="#{data.isLocked()}"/>
</div>
</div>
<!-- works perfectly to set the id -->
<span id="edit_#{data.id}">#{data.desc} #{index}</span>
<!-- doesnt work - maybe of the rendering moment to set the id? -->
<p:panelGrid id="edit_#{data.id}" rendered="#{view.edit}">
<p:outputLabel for="desc" value="#{msg.text}" />
<p:inputText id="desc" value="#{view.selectedValue.desc}" />
</p:panelGrid>
如果我想编辑该 div,如何为 panelGrid 设置动态 ID 以通过 commandButton click 更新它?+ 如何在编辑时切换 div?还是有其他解决方案?我不允许使用 JavaScript/jQuery。
非常感谢!
干杯,JohnRamb0r
解决方案
我想说你几乎是在反对 JSF 以及它在你的代码示例中的工作方式。在向您展示一个工作示例之前,我想在这里说一些与良好实践相关的事情:
- 不要直接调用方法,使用属性引用的内置翻译。对的引用
data.locked
将自动转换为对的调用data.isLocked()
。首选调用data.locked
,因为它会导致框架对其进行评估,而不是您发送已评估的值。 - 使用 JSF - 不要反对它。在您的示例代码中有很多不必要的 id 和不需要的标签和索引的使用。保持简单并使用框架。直接引用对象而不是引用 id - 它简化了代码并使其更易于在页面本身上使用。
- 使用动作作为业务逻辑和结果的主要执行者。动作侦听器是预先执行的,可用于拦截或停止主要动作的执行。因此,它们适合用作执行业务逻辑之前的验证步骤。
- 标记您的活动。
on<Something>
在命名接收用户事件的方法时,最好使用命名约定。这使您可以清楚地识别它们。
我为您的代码制作了一个小型工作示例(这使用Lombok和Apache Commons);
@Data
@Named
@ViewScoped
public class DataListViewBackingBean implements Serializable {
private Entity entity;
private Entity selectedEntity;
private List<Entity> dataEntities;
@PostConstruct
private void init() {
dataEntities = new ArrayList<>();
for (int i = 0; i < 10; i++) {
dataEntities.add(new Entity(i, RandomUtils.nextBoolean(),
RandomStringUtils.randomAlphabetic(30)));
}
}
@Data
@AllArgsConstructor
@EqualsAndHashCode(exclude = {"locked","description"})
public class Entity {
private int id;
private boolean locked;
private String description;
}
public void onEdit(Entity entity) {
selectedEntity = entity;
}
public void onDelete(Entity entity) {
dataEntities.remove(entity);
selectedEntity = null;
}
}
上面的代码初始化了一个包含十个实体的数据列表,并用随机数据填充它。我有幸更改data
为entity
. 当涉及到您的 HTML 代码时,我觉得它需要一些清理。JSF 的定义看起来像这样;
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Data list test</title>
</h:head>
<h:body>
<h:form id="items">
<p:dataList type="definition" value="#{dataListViewBackingBean.dataEntities}" var="entity">
<div class="ui-g">
<div class="ui-g-8">
#{entity.description}
</div>
<div class="ui-g-4" style="text-align: right">
<p:commandButton value="Edit" disabled="#{entity.locked}" action="#{dataListViewBackingBean.onEdit(entity)}" update=":edit" />
<p:commandButton value="Delete" disabled="#{entity.locked}" action="#{dataListViewBackingBean.onDelete(entity)}" update="@form :edit" />
</div>
</div>
</p:dataList>
</h:form>
<h:form id="edit">
<p:outputPanel rendered="#{dataListViewBackingBean.selectedEntity != null}">
<h1>Editing...</h1>
<p:inputText placeholder="Description" value="#{dataListViewBackingBean.selectedEntity.description}" />
<p:commandButton value="Save" update=":items" />
</p:outputPanel>
</h:form>
</h:body>
</html>
请注意编辑div/outputPanel
是如何包装在另一个容器(表单)中的。如果我们跳过包装,而是直接在包装容器上推送更新,则容器的rendered
标签将永远不会在刷新期间更新,因此 div 将永远不会出现。在这种特殊情况下,这就是为什么在容器外部而不是内部定义表单的原因。
此示例使用@ViewScoped
bean,因此只要您留在页面上,支持数据应该保持不变。如果您重新加载页面,您将获得一个包含新实体的新数据集,因为这将重新初始化一个支持 bean 并@PostConstruct
再次调用。
也可以看看
推荐阅读
- azure - 用于列出代理池和作业运行的 Azure CLI 命令
- sql - 将列值与 Oracle 中的先前记录进行比较
- android - 寻找某个回调的非常基本的术语
- reactjs - 动态添加 colDefs
- wordpress - 无法在移动浏览器上运行的 Wordpress 网站在桌面上运行良好 - 重定向太多
- flutter - Flutter 从外部上下文获取上下文值
- python - 用给定的数字减去数据框列中的每个元素 - python
- javascript - 在 react js 中实现递归 onClick 事件
- selenium - Selenium Firefox Headless Connect 远程调试器
- python - 我如何能够在同一数据框中将值从一列“更新”到另一列?