GWT Tree Widget getElement() method not working as expected - gwt

I have a GWT UI Panel Created with Elements , and I need to add a GWT tree to the UI
I did
TreeItem department = new TreeItem("Packages");
TreeItem salesDepartment = new TreeItem("Package1");
TreeItem marketingDepartment = new TreeItem("Package2");
TreeItem manufacturingDepartment = new TreeItem("Package3");
TreeItem employee1 = new TreeItem("Flight");
TreeItem employee2 = new TreeItem("Cruilse");
TreeItem employee3 = new TreeItem("Flight");
salesDepartment.addItem(employee1);
salesDepartment.addItem(employee2);
salesDepartment.addItem(employee3);
TreeItem employee4 = new TreeItem("Cruise");
TreeItem employee5 = new TreeItem("Hotel");
marketingDepartment.addItem(employee4);
marketingDepartment.addItem(employee5);
TreeItem employee6 = new TreeItem("Cruise");
TreeItem employee7 = new TreeItem("Hotel");
manufacturingDepartment.addItem(employee6);
manufacturingDepartment.addItem(employee7);
department.addItem(salesDepartment);
department.addItem(marketingDepartment);
department.addItem(manufacturingDepartment);
Tree tree = new Tree();
tree.addItem(department);
// consider that treeDiv is already added
private Element treeDiv = DOM.createDiv();
DOM.appendChild( treeDiv , tree.getElement() );
when I added the tree widget as a Element it shows only text inputs no expand buttons or anything,its not working as a tree just texts.
please tell me is there any fix for this.

// consider that treeDiv is already added
private Element treeDiv = DOM.createDiv();
DOM.appendChild( treeDiv , tree.getElement() );
when I added the tree widget as a Element it shows only text inputs no expand buttons or anything,its not working as a tree just texts. please tell me is there any fix for this.
I'm not sure what that comment means, given that the tree was just created so could not have already been added, but even if that was a concern, I'm not sure why we must use the tree's element directly. If there are more pieces to this question you are skipping, please add them. For example: what is the treeDiv ever added to?
As a direct answer to the question, Don't Do This. Instead, use the widget's own add method, add widgets to other widgets, rather than directly manipulating the dom elements.
For example, if you are adding the tree to the <body> directly, this would look like this:
RootPanel.get().add(tree);
Or, if you already have a parent widget (called here panel), just add it directly to that parent:
panel.add(tree);
The reason for this is that the Widget wiring has its own event wiring that needs to be set up - to avoid memory leaks in the crappier browsers, it is important to make sure that event wiring is removed when the widgets are taken off the page. See http://www.gwtproject.org/articles/dom_events_memory_leaks_and_you.html for more details, but the short version is that after actually adding a widget's dom element to the greater dom, the widget's onAttach must be called, and any children widgets must also have their onAttach called as well. This is automatically done when adding a widget to another widget - you should stick to that API.

Related

SmartGWT expanding Tree till a child node

I have created a tree using the following code. Is there a way to expand the tree till a particular child node from the code?
TreeGrid treeGrid = new TreeGrid();
Tree tree = new Tree();
tree.setRoot(new TreeNode("root", new TreeNode("File",
new TreeNode("FileChild")), new TreeNode("Edit", new TreeNode(
"EditChild", new TreeNode("EditGrandChild"))), new TreeNode(
"Window")));
treeGrid.setData(tree);
treeGrid.draw();
I want to display the "EditGrandChild" node when the tree is rendered. How do i do that?
Thanks
I used to open some parts of a treegrid depending on the result of a search and I used this bits of code
TreeNode[] tabNode = leTree.getParents(t);
leTree.openFolders(tabNode);
Hope it could help...

Inserting GWT widget into a div element

I'm using a GWT library (gwt-openlayers) which allows me to create a map popup containing arbitrary HTML, similar to Google Maps. I need this HTML to contain a GWT Button widget.
I'm creating some HTML elements on-the-fly like this:
Element outerDiv = DOM.createDiv();
outerDiv.getStyle().setOverflow(Overflow.HIDDEN);
outerDiv.getStyle().setWidth(100, Unit.PCT);
outerDiv.appendChild(new HTML(mapPOI.getHtmlDetails()).getElement());
Button popupButton = new Button("View Property");
popupButton.getElement().getStyle().setFloat(com.google.gwt.dom.client.Style.Float.RIGHT);
outerDiv.appendChild(popupButton.getElement());
Then I'm getting the source HTML for these elements by calling
String src = outerDiv.toString();
and inserting this html into my map marker. Now my map marker displays the content ok, including the button. However, the button won't respond to any events! From what I can gather, this is because the buttons onAttach() method is never being called.
Is there a better way to do this?
Thanks,
Jon
~~~~EDIT~~~~
I'm now trying a new way of doing this, which seems to be the accepted method looking at other similar posts.
First I'm creating my div:
String divId = "popup-" + ref;
String innerHTML = "<div id=\"" +divId + "\"></div>";
Then I'm adding this to my map popup and displaying it (which adds it to the DOM). After the popup has been displayed, I'm getting the Element as follows and trying to wrap a HTMLPanel around it:
Element element = Document.get().getElementById(divId);
HTMLPanel popupHTML = HTMLPanel.wrap(element);
My div element is successfully retrieved. However, HTMLPanel.wrap(element); doesn't complete. The reason for this is that wrap(..) calls RootPanel.detachOnWindowClose(Widget widget), which includes the following assertions:
assert !widgetsToDetach.contains(widget) : "detachOnUnload() called twice "
+ "for the same widget";
assert !isElementChildOfWidget(widget.getElement()) : "A widget that has "
+ "an existing parent widget may not be added to the detach list";
I put some breakpoints in and it seems that the 2nd assertion is failing!
Does anybody have any idea why this might be the case? Should failing this assertion really result in a complete failure of the method (no return)?
Your first approach is good, you just need to register onClick event for your button like this:
DOM.sinkEvents(popupButton.getElement(), Event.ONCLICK);
DOM.setEventListener(popupButton.getElement(), new EventListener() {
#Override
public void onBrowserEvent(Event event) {
//implement the logic after click
}
});
I have checked this, it works 100%!
You might try something like
RootPanel.get("idOfYourMapMarker").add(popupButton);
See RootPanel.get()
Unfortunately, RootPanels are AbsolutePanels which aren't so nice for layout but could work if you just have a simple button to add. You could also try RootLayoutPanel which will give you a LayoutPanel (also not so nice when you just want things to flow). You might end up creating a container widget that does the layout for you, and adding that to the RootPanel.
SimplePanel is a DIV. Perhaps that can be used instead?
You added the element, but you have to keep the hierarchy of the actual GWT Widgets too.
I don't see a clean way to do this, but you could use something like jQuery to grab the button by and ID and add a click handler back to it that would call the original click handler.
private static native void registerEvents(String buttonId, MyClass instance)/*-{
var $ = $wnd.$;
//check click
$('#'+buttonId).live('click', function(e) {
e.preventDefault();
instance.#com.package.MyClass::handleButtonClick(Lcom/google/gwt/event/dom/client/ClickEvent;)(null);
});
}-*/;
Call this registerEvents() either in your onAttach or constructor.
I once had a similar problem. You can use the gwt-openlayer's MapWidget as follows:
private MapWidget createMapWidget() {
final MapOptions defaultMapOptions = new MapOptions();
defaultMapOptions.setDisplayProjection(DEFAULT_PROJECTION);
defaultMapOptions.setNumZoomLevels(TOTAL_ZOOM_LEVELS);
MapWidget mapWidget = new MapWidget(MAP_WIDGET_WIDTH, MAP_WIDGET_HEIGHT, defaultMapOptions);
map = mapWidget.getMap();
return mapWidget;
}
And then add it to any panel be it vertical or horizontal.
MapWidget mapWgt = createMapWidget();
VerticalPanel mainPanel = new VerticalPanel();
mainPanel.add(mapWgt);
...
... add whatever you want
...
You can finally add the created Panel(containing the MapWidget and the gwt widget) to the PopupPanel. Also, you should now be able to add handlers to the gwt button.

GWT - Can you nest FormPanels inside FormPanels?

I'm trying to nest a FormPanel inside another FormPanel. It seems that any field in the nested panel is never rendered.
This screenshot is produced by the code below it:
TabItem tabItem = new TabItem("Tab Item");
FormPanel formPanel = new FormPanel();
formPanel.setHeading("Form Panel");
formPanel.setFrame(true);
TextField textField = new TextField();
textField.setFieldLabel("Text Field");
FormPanel nestedPanel = new FormPanel();
nestedPanel.setHeading("Nested Panel");
TextField nestedField = new TextField();
nestedField.setFieldLabel("Nested Field");
nestedPanel.add(nestedField);
TextField anotherField = new TextField();
anotherField.setFieldLabel("Another Field");
formPanel.add(textField);
formPanel.add(nestedPanel);
formPanel.add(anotherField);
tabItem.add(formPanel);
tabPanel.add(tabItem);
Can anyone explain why the nested field does not show in the nested panel?
I've also tried using a CaptionPanel instead of a FormPanel as the nested panel, but the caption panel does not show the field label.
Any suggestions as to how I can get this to work would be most welcome. Thank you :)
As Jason mentioned, <form> cannot be nested. The GXT FormPanel draws a form as part of how it works, so consider drawing this layout in another way.
To emulate the appearance of the FormPanel, there are two basic steps.
To get the header, border, create a ContentPanel, and add the content to that
To get the GXT 2 layout of drawing the field labels, use a FormLayout in the content panel.
This will look something like this (from your example)
//...
ContentPanel nestedPanel = new ContentPanel(new FormLayout();
nestedPanel.setHeading("Nested Panel");
TextField nestedField = new TextField();
nestedField.setFieldLabel("Nested Field");
nestedPanel.add(nestedField);
//...
The outer field will still manage any binding, and the nested field will look as if they were in a FormPanel. If not using other features of the FormPanel, it may in general make more sense to use a ContentPanel (or LayoutContainer, if you don't want the border/header) with a FormLayout.

display open nodes in a GWT Tree

I create a GWT Tree, and I would like it to be initially displayed with open nodes. Let's take the standard Tree example from GWT javadocs:
public class TreeExample implements EntryPoint {
public void onModuleLoad() {
// Create a tree with a few items in it.
TreeItem root = new TreeItem("root");
root.addItem("item0");
root.addItem("item1");
root.addItem("item2");
// Add a CheckBox to the tree
TreeItem item = new TreeItem(new CheckBox("item3"));
root.addItem(item);
Tree t = new Tree();
t.addItem(root);
// Add it to the root panel.
RootPanel.get().add(t);
}
}
I want it initially displayed as:
root
item0
item1
item2
item3
Now, I thought that it was as simple as setting the state of the TreeItem that I want to be opened by calling setState(true): javadoc for setState says "Sets whether this item's children are displayed". However, if I add for example
root.setState(true);
to the above example, I don't get the expected effect. Apparently nothing changes when I do root.setState(true); or root.setState(false);: the tree is always displayed with its nodes closed.
How do I get the desired behaviour?
The call to setState() depends on the sequence of the method calls to TreeItem and Tree (as stated here).
As a rule of thumb call setState(true) after adding all the items to the TreeItem and after adding the root item to the Tree.

How to add a GWT click listener to an Image?

I want to click on an image and therefore want to register (e.g.) a ClickHandler. The image I get from a ClientResource. This works so far to set the image into a table cell:
MyResources.INSTANCE.css().ensureInjected();
Image colorImage = new Image( MyResources.INSTANCE.colorImage() );
Element colorImageElement = colorImage.getElement();
colorImage.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
System.out.println( event );
}
} );
TableElement table = Document.get().createTableElement();
TableRowElement headRow = table.insertRow(-1);
headRow.insertCell(-1).appendChild( colorImageElement );
RootPanel.get().getElement().appendChild( table );
How can I add a listener to the icon? I tried ClickHandler and to put the image on a PushButton and get the Element from this PushButton but all don't work.
But mind, if I add the widget (Image is a Widget) to a panel it works!
RootPanel.get().add( colorImage );
But I am not working with widgets here but with the Element. So the handler disappears and that's the point I don't get how to preserve this added handler information.
In the end I would like to build a table with different rows where I can click on the icon I get a popup menu and thereby change the colour of the row.
You should be able to just add a ClickHandler (or a MouseDownHandler if that fits your needs better).
Like this:
colorImage.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// Do something....
}
});
Don't unwrap your widget and append only the DOM elements. The Widget class allows your code to refer to both elements and events at the same time, and deals with possible memory leaks, as well as grouping your code in logical ways.
This might make sense for other frameworks, but in GWT you almost always want to work with the Widgets directly, adding them together, then appending them to the RootPanel.
If you really want to use a html table to build this up, look at the com.google.gwt.user.client.ui.HTMLTable subclasses, com.google.gwt.user.client.ui.Grid and com.google.gwt.user.client.ui.FlexTable. This probably should never be necessary, unless you are adding multiple items to the table - when trying to specify layouts, use actual layout classes.
did you tried to add image.sinkEvents( Event.ONCLICK | Event.MOUSEEVENTS )?
The image has to be inside a focus widget. I don't know why that is, but somewhere the events don't get propagated right and the DOM events don't fire.