java - Apache Wicket AjaxRequestTarget ListView 组件不刷新或更新
问题描述
我对 apache wicket (字面意思)真的很陌生,我有一个任务需要在添加项目(来自引导模式框)后通过 ajax 刷新表(ListView)。
假设我有一个显示实验室详细信息(房间)的页面和一个显示实验室设备列表的表格。
要添加实验室设备,有一个按钮,单击...时会显示一个模式框(弹出窗口),用户可以在其中从下拉列表中选择实验室设备。
当添加实验室设备时(从弹出模态),模态将被关闭/隐藏,然后表格组件将通过 ajax 刷新。
问题:
刷新组件的代码contentDevices
似乎不起作用。添加实验室设备后,我可以看到它反映在数据库中。但是由于未知原因,带有显示实验室设备列表的表格的容器没有刷新。
我想contentDevices
在添加/删除实验室设备后刷新容器/组件。该组件contentDevices
有一个子组件,它是一个显示实验室中设备列表的表格。
现在的问题是,我仍然需要刷新页面(浏览器刷新),以便新添加的实验室设备能够反映。
顺便说一句,Device
类没有onBeforeRender()
。此类的新实例将替换现有的contentDevices
.
已经好几天了,但我不知道为什么它不令人耳目一新。如果这只是普通的 HTML/JS,这真的很容易,但我对 apache wicket 真的一无所知。
page/html 结构是这样的:
结构或布局:
<!-- HTML document -->
<Page>
...
<!-- Content section -->
<div id="content">
<div id="detailsContainer">
...
</div>
<div id="devicesContainer">
...
<div id="contentDevices">
<!-- Other components (ex. table) here that needs to be refreshed after adding/removing device -->
</div>
...
</div>
</div>
</div>
...
</Page>
代码:
...
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
super.onSubmit(target, form);
laboratoryService.addDevice(this.laboratoryModel.getObject(), selectedDevice.getLabel(), selectedDevice.getValue());
// Refresh laboratory model and update the list of laboratory devices from DB
Laboratory laboratory = laboratoryService.getLaboratory(this.laboratoryModel.getObject().getId());
this.laboratoryModel = new Model<>(laboratory);
// Start: refreshing `contentDevices`
WebMarkupContainer cContent = (WebMarkupContainer) getPage().get("content");
WebMarkupContainer devicesContainer = (WebMarkupContainer) cContent.get("devicesContainer");
Component cDevices = devicesContainer.get("contentDevices");
cDevices.replaceWith(new Device("contentDevices", getMyPageContext(), this.laboratoryModel));
devicesContainer.addOrReplace(cDevices);
cContent.addOrReplace(devicesContainer);
target.add(cContent);
// End refreshing `contentDevices`
// Hide bootstrap modal box
MyUtil.hideBootstrapModalBox(target, "[data-locator=addDeviceModalBox]");
// showCustomAlert - show success message
target.appendJavaScript("showCustomAlert('success', 'Added laboratory device.', true);");
}
...
设备类:
public class Device extends AbstractMyPagePanel {
private static final long serialVersionUID = 1L;
@Autowired
private LaboratoryService laboratoryService;
private IModel<Laboratory> laboratoryModel;
public Device(String id, MyPageContext myPageContext, IModel<Laboratory> laboratoryModel) {
// `laboratoryModel` is passed until most parent class which is `org.apache.wicket.markup.html.panel.Panel`
super(id, myPageContext, laboratoryModel);
this.laboratoryModel = laboratoryModel;
add(createAddDeviceButton());
add(new AddDeviceModalBox("addDeviceModalBox", myPageContext, this.laboratoryModel));
add(createRowsContainer());
setOutputMarkupId(true);
}
private Component createAddDeviceButton() {
return new WebMarkupContainer("addDeviceButton") {
private static final long serialVersionUID = 1L;
@Override
protected void onConfigure() {
super.onConfigure();
setVisible(isAdmin());
}
};
}
private Component createRowsContainer() {
WebMarkupContainer result = new WebMarkupContainer("rowsContainer") {
private static final long serialVersionUID = 1L;
@Override
protected void onConfigure() {
super.onConfigure();
setVisible(CollectionUtils.isNotEmpty(this.laboratoryModel.getObject().getRoomDevices()));
setOutputMarkupPlaceholderTag(true);
}
};
// This part here is OK, laboratory model and devices are updated
System.out.println("\n");
System.out.println("CREATE-ROW-CONTAINER");
System.out.println("---------------------------------------------");
System.out.println("[device-count]: " + this.laboratoryModel.getObject().getRoomDevices().size());
System.out.println("---------------------------------------------");
System.out.println("\n");
System.out.println("\n");
System.out.println("LABORATORY-DEVICES");
System.out.println("---------------------------------------------");
for (LaboratoryDevice device : this.laboratoryModel.getObject().getRoomDevices()) {
System.out.println("[device]: " + device.getName());
}
System.out.println("---------------------------------------------");
System.out.println("\n");
// This part here is not OK, `populateItem()` is not called
// `rows.children` is null, but `rows.data.transientModelObject` is updated and contains the latest added laboratory device
// Same goes when `add` is used instead of `addOrReplace`, the issue is still there
result.addOrReplace(new ListView<LaboratoryDevice>("rows", this.laboratoryModel.getObject().getRoomDevices()) {
private static final long serialVersionUID = 1L;
@Override
protected void populateItem(ListItem<LaboratoryDevice> item) {
LaboratoryDevice device = item.getModelObject();
item.add(new Label("name", device.getName()));
item.add(new Label("sn", device.getSn()));
item.add(new WebMarkupContainer("removeButton").setVisible(isAdmin()));
item.add(new RemoveLaboratoryDeviceModalBox("removeLaboratoryDeviceModalBox",
getMyPageContext(), item.getModel()));
}
});
return result;
}
}
我知道这是非常基本的,但我在网上找不到任何真正有效的东西:(
谢谢!
解决方案
您应该检查是否有任何错误:
- 服务器日志中的错误
- 浏览器的开发工具控制台中的错误
我猜开发工具中有一个 JS 错误,说 Wicket 找不到带有 id 的 HTML 元素contentXYZ
。如果是这种情况,那么请确保您调用cContent.setOutputMarkupId(true)
了cContent
实例化的位置,即在页面的构造函数中。
您不需要cDevices.setOutputMarkupId(true)
,因为您从不添加cDevices
到target
.
并且大多数时候调用为时已晚setOutputMarkupId(true)
,onXYZ(AjaxRequestTarget)
因为整个页面已经呈现并且组件/元素需要呈现一个id
属性,该属性将在稍后 Ajax 响应尝试查找旧 HTML 元素并将其替换为新元素时使用(在onXYZ(AjaxRequestTarget)
.
推荐阅读
- swift - 访问字典键/值时出现模棱两可的错误
- vb.net - 贴标机上打印的 Code39 不可读
- java - Java - 如何在循环中每 n 次重复换行
- javascript - 使用 Slack API 设置提醒
- linux - 如何从内核识别并向应用程序发送消息?
- javascript - Pentaho JavaScript JSON - 基于键将 json 对象连接到现有的 JSON 文档中
- .net - `.NET 编译器平台 SDK` 和 `C# 和 Visual Basic Roslyn 编译器`之间的区别
- c++ - 在 boost::spawn 中捕获指针
- racket - BSL(如何设计程序):如何将代码从单独的文件导入定义区域?
- spring-integration - Spring集成流测试