Reputation: 47
hope you can help me with this because it has been bugging me for a few days now.
I have a wicket DataTable filled with 16 columns. Every row can have some child info (if it has a '+' button is shown in the first cell). Since the child info is just some regular text with a date on when it was entered, I did not want to use a real TreeData object. I have been trying to make the '+' button into an AjaxFallbackButton, which works, but my child data is rendered inside the first cell of the row, which is very impractical.
I am now trying to dynamically create a new row by prepending some JS on the target:
target.prependJavaScript(String.format("var item=document.createElement(\"tr\"); item.id=\"%s\"; $(\"#%s\").after(item);", newChild.getId(), rowId));
This is great because it actually creates a new tag inside my page. But how do I get my new data inside this newly rendered HTML? I guess my problem is that Wicket does not 'know' the new row and if I add the new wicket Item (the container in Wicket with the new row) to the Wicket DataTable and add the body of the DataTable to the target then now rendering of my new row is done.
My markup for the page: [table]
My custom DataTable extension Java code (extended to make sure all outputMarkUp is added): @Override protected void onInitialize() { super.onInitialize(); this.addTopToolbar(new NavigationToolbar(this)); this.addTopToolbar(new HeadersToolbar<>(this, (ISortableDataProvider)this.getDataProvider())); this.addBottomToolbar(new NoRecordsToolbar(this)); this.setOutputMarkupId(true); }
@Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(CssReferenceHeaderItem.forReference(WarehouseToolbarCssReference.get()));
}
@Override
protected Item<T> newRowItem(String id, int index, IModel<T> model) {
Item<T> item = super.newRowItem(id, index, model);
this.lastId = Integer.valueOf(id);
item.setMarkupId(this.getId() + item.getId());
return item;
}
The first column uses a custom Panel to fill up the cells in the column, but after a lot of tries and tests, I'm actually ending up with the regular Node from Wicket itself:
<wicket:panel xmlns:wicket="http://wicket.apache.org">
<a wicket:id="junction"></a>
<span wicket:id="content" class="tree-content">[content]</span>
cellspacing="0" wicket:id="reasonData">[Reason data]</table>-->
</wicket:panel>
And finally the code that creates the new row and fills up the necessary data (which is itself a new DataTable) and also fills the ajax-target:
public void onClick(AjaxRequestTarget target) {
Integer currentRowIndex = Integer.valueOf(this.findParent(Item.class).findParent(Item.class).getId());
String rowId = this.findParent(Item.class).findParent(Item.class).getMarkupId();
Item<IColumn<OldOrder, String>> newChild = null;
this.dataTable.setVisible(true);
newChild = new Item<>(String.valueOf(this.findParent(DataTable.class).getLastId() + 1), currentRowIndex * -1, null);
newChild.setOutputMarkupId(true);
target.prependJavaScript(String.format("var item=document.createElement(\"tr\"); item.id=\"%s\"; $(\"#%s\").after(item);", newChild.getId(), rowId));
this.populateChildRow(newChild); // This is where the new row gets filled with the new data
Component rows = this.findParent(DataTable.class).getBody().get("rows");
if (rows instanceof WebMarkupContainer) {
((WebMarkupContainer)rows).add(newChild);
}
target.add(this.findParent(DataTable.class).getBody());
}
// This is where the new row gets filled with the new data
private void populateChildRow(Item<IColumn<ParentClass>, String>> item) {
RepeatingView cells = new RepeatingView("cells"){
@Override // Overridden to check if this gets executed... it doesn't
protected void onAfterRender() {
super.onAfterRender();
String stop = "STOP";
}
};
item.add(cells);
Item<?> cellItem = new Item<>("arbitrary", 1, null);
cells.add(cellItem);
cells.setVisible(false);
cells.setOutputMarkupId(true);
cells.add(AttributeAppender.append("colspan", this.findParent(DataTable.class).getColumns().size()));
this.dataTable.setOutputMarkupId(true);
cellItem.add(this.dataTable); // The DataTable with the child data
}
Besides the fact I should clean out some code, the child data is never rendered. Can someone please shed some light on this?
Upvotes: 1
Views: 798
Reputation: 17513
I'd suggest to go with JavaScript all the way, i.e. create a new <tr>
and then populate it with JS. Don't use Wicket's Item
at all.
When the expand link is clicked do something like target.appendJavaScript("yourOwnFunction('"+link.getMarkupId()+"', "+someDataAsJson+")");
. So yourOwnFunction()
will use the link id to find its closest parent <tr>
and then with JS you can append the new row after it. Once you have the row created you could use the JSON with the data to populate it as you need.
Upvotes: 0