Reputation: 2038
I am really new with apache wicket (Literally) and I got a task that needs refreshing a table(ListView) via ajax after adding an item (from bootstrap modal box).
Let's say I have a page display the laboratory details (room) and a table displaying the list of laboratory devices.
To add a laboratory device, there is a button that when clicked... will display a modal box (popup) where the use can select a laboratory devices from a dropdown.
When a laboratory device is added (from popup modal), the modal will be closed/hidden, then the table component will be refreshed via ajax.
Problem:
Code for refreshing the component contentDevices
seems not working. After adding the laboratory device, I can see that it is reflected in the database.
But for unknown reasons, the container with table showing the list of laboratory devices is not refreshing.
I would like to refresh the container/component contentDevices
after adding/removing laboratory device. The component contentDevices
has a child which is a table that displays the list of devices in the laboratory.
The issue now is, I still need to refresh the page (browser refresh) inorder for the newly added laboratory device to reflect.
By the way, Device
class does not have onBeforeRender()
. The new instance of this class will replace the existing contentDevices
.
It's been days already but I cannot figure out why it's not refreshing. This is really easy if this is just plain HTML/JS, but I am really clueless with apache wicket.
The page/html structure is something like this:
Structure or Layout:
<!-- 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>
Code:
...
@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);");
}
...
Device class:
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;
}
}
I know this is very basic but I could not find anything the really works in the net :(
Thanks!
Upvotes: 0
Views: 1457
Reputation: 17533
You should check whether there are any errors:
I guess there is an JS error in the Dev Tools saying that Wicket cannot find an HTML element with id contentXYZ
. If this is the case then make sure you call cContent.setOutputMarkupId(true)
where cContent
is instantiated, i.e. in the constructor of the page.
You do not need cDevices.setOutputMarkupId(true)
because you never add cDevices
to the target
.
And calling setOutputMarkupId(true)
in onXYZ(AjaxRequestTarget)
most of the time is too late because the whole page is already rendered and the component/element needs to render an id
attribute which will be used later when the Ajax response tries to find the old HTML element and replace it with the new one (created or updated in onXYZ(AjaxRequestTarget)
.
Upvotes: 0