Instead of doing the override method, upgrade to Wicket 1.5 and utilize the new event bus to communicate between your components. You can create a custom, type-safe, event that is specific to your component's use case: for example "ItemAddedToShoppingCart" or "GlobalThermoNuclearWarStarted.
Instead of doing the override method, upgrade to Wicket 1.5 and utilize the new event bus to communicate between your components. You can create a custom, type-safe, event that is specific to your component's use case: for example "ItemAddedToShoppingCart" or "GlobalThermoNuclearWarStarted". The linked article in the 1.5 migration guide provides enough information on how to set up things.
I'm not sure I understand que question correctly. Your BasePage defines a left column with the TreePanel and lets subclasses expand themselves inside the right column div. You usually put a BodyPanel inside BasePages's subclasses.
And now you want to invoke a BodyPanel's method on some event on the TreePanel. You could do it with an overridable method on BasePage, which would be called in TreePanel through getPage(). Your child pages would override that method, and its implementation would call the BodyPanel they're holding.
Public class BasePage ... { // Hook public void treePanelSelected(Object someObject) { } ... } public class ChildPage extends BasePage ... { BodyPanel bodyPanel; @Override public void treePanelSelected(Object someObject) { bodyPanel. SelectionChanged/(someObject); } ... } public class TreePanel ... { ... @Override protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode node) { super. OnNodeLinkClicked(target, node); DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)node; Unit unitObject =(Unit) treeNode.getUserObject(); ((BasePage)getPage()).
TreePanelSelected(unitObject); } } From my ignorance on your specific needs and details of implementation, I don't see why is subclassing the BasePage necessary. You could add the BodyPanel right there in the BasePage and control it from the same class.
1 thanks for your time and nice example. Finally I've done it with event bus. – Shahriar Sep 30 at 10:02 You're welcome!
You've done the right thing. I'm stuck with wicket 1.3 by now, so there are so much nice improvements still unknown to me :( – Xavi López Sep 30 at 10:05.
There are two ways to do this. One is cleaner, but requires more code. The other is quick and dirty.
Method 1: (Good) Since your parent page is being extended, you can provide an abstract method in the parent like protected abstract WebMarkupContainer getBodyPanel(); that is implemented in your child page and returns the appropriate panel. Then, you can call that method from the panel in your parent page. This is similar to the overrideable method suggested by the other user.
Method 2: (Bad) The Wicket Component erarchy is shared between the parent and child pages. So, if you make sure that your bodyPanel has a unique wicketId and is added directly to the root of the page, you can probably just call get("bodyPanelId"); and it will return the proper panel.
I think placing an abstract getBodyPanel() would work, indeed, but would be imo poor OOP practice. The basepage doesn't have to know that it can have subpanels, and definitely should not have to provide a method to get them. What it could be aware of is that it has a treepanel that can trigger events to it.
Besides, it'd make basepage abstract. – Xavi López Sep 29 at 10:54 Hrm. Agreed.
I'm going to leave this here, but bumping up your post :) The getBodyPanel() can be helpful in other scenarios. – jbrookover Sep 29 at 11:01 Thank you. That makes sense, however, if subclassing basepage is a right decision in the first place.
From the info the OP provided, and assuming all child classes only add a BodyPanel, it seems that BodyPanel (or at least a generalization of it) should actually be part of basepage. – Xavi López Sep 29 at 11:21.
When I was facing the problem, I thought of two ways to solve this (pre 1.5): a) implement a variation of the observer pattern to notify other component of events like outlined here: Realising complex cross-component ajax actions in wicket - The observer way b) using wicket visitors to traverse the component tree doing the same. I decided to go for variant a) but this introduces coupling from your component to your page-implementation which leads to problems when testing panels on their own. So maybe b) might be the better idea but since my application is running quite smoothly with a) implemented and the next big step will be switching over to 1.5 and the event bus, I haven't yet tried b).
2 The event bus was originally developed against 1.4, you can find the patch at issues.apache. Org/jira/browse/WICKET-1312. Might be interesting to see if you can apply it to your 1.4.X application – Martijn Dashorst Sep 30 at 7:49 thanks, your example is cool.
Since I've moved to 1.5 I preferred to use event bus. – Shahriar Sep 30 at 10:01 @MartijnDashorst As this implements b), I think I'll give it a try, just to see how it works (patching 1.4)... Sounds fun ;) – Nicktar Sep 30 at 11:23.
Thanks all, After reviewing all the nice options I finally opted out for the event bus way defined by martijn. What I did is I have created an event payload and connected the panels for the talking. I also needed to pass the selected Id / entity to the receiving panel.Is there a way to set a compound property model of the receiving panel according to the model of the tree element so that I don't need to do the model manually?
I did like this for the time being: public class TreeNodeClickUpdate { private final AjaxRequestTarget target; private final long selectedId; /** * Constructor * * @param target * @param selectedId */ public TreeNodeClickUpdate(AjaxRequestTarget target, long selectedId) { this. Target = target; this. SelectedId = selectedId; } /** @return ajax request target */ public AjaxRequestTarget getTarget() { return target; } public long getSelectedId() { return selectedId; } } On the sender side I've done like this: send(getPage(), Broadcast.
BREADTH, new TreeNodeClickUpdate(target, unitObject.getId())); And on the receiving end I got it like this: @Override public void onEvent(IEvent event) { super. OnEvent(event); if (event.getPayload() instanceof TreeNodeClickUpdate) { TreeNodeClickUpdate update = (TreeNodeClickUpdate)event.getPayload(); setSelectedId(update.getSelectedId()); //sets to id field of panel update.getTarget(). Add(this); } } and for just as an example in my receiving panel, to get the value I have created a label like this: label = new Label("label",new PropertyModel(this,"selectedId")); Later, in reality I want to get information from the entity and show in form.
Is there a nice way to pass models in a better way or I should pass as a parameter in event payload.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.