SmartGWT tab losing GWT based contents - gwt

I have written very basic GWT application where SmartGWt tabs render with label on both tabs.
Problem I am facing here is, when I put GWT based label in second tab and reload application, first tab renders SmartGWT based label but when i click on second tab to look GWT label, it doesn't appear and also I am surprised why first tab content is removed as It was appearing earlier before clicking on second tab.
Please have a look into below code.
package com.test.client;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.tab.Tab;
import com.smartgwt.client.widgets.tab.TabSet;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
public class TestGWT implements EntryPoint
{
public void onModuleLoad()
{
TabSet tabSet = new TabSet();
tabSet.setWidth("400px");
Tab tab1 = new Tab("Tab1");
Canvas pane = new Canvas();
pane.addChild(new com.smartgwt.client.widgets.Label("test label"));
tab1.setPane(pane);
Tab tab2 = new Tab("Tab2");
Canvas pane2 = new Canvas();
pane2.addChild(new Label("test label2")); // I need to put GWT widget in SmartGWT tab but it does not render in this tab. Also, it removes contents from first tab
tab2.setPane(pane2);
tabSet.addTab(tab1);
tabSet.addTab(tab2);
RootPanel.get("testid").add(tabSet);
}
}
When I set second SmartGWT tab to appear first which has GWT widget then things are working fine.
I am using GWT-2.6.1
Please share your thoughts here!
Regards,
Shobhit

Although I agree on the cause of the problem being RootPanel.get("testid").add(tabSet), the solution is replacing that line with:
tabSet.show();
Keep in mind that in SmartGWT, you should add components to other components using add(). Trying to add components using their IDs is prone to errors.
Finally, keep in mind that Isomorphic discourages mixing SmartGWT's components with components from other libraries. While this is unavoidable sometimes, if you can avoid it in your application, you should, because this is a very common source for bugs. See my comments below for additional sources for these claims.

The problem is adding the TabSet to the RootPanel. So you receive an
A widget that has an existing parent widget may not be added to the detach list.
error.
Change RootPanel.get("testid").add(tabSet); to
tabSet.setHtmlElement((Element) Document.get().getElementById("testid"));
tabSet.draw();
and it will work fine.

Related

Wicket AjaxLink javascript handler shows strange behaviour

I have a ListView that displays a list of Panels, one below the other. Every panel features a button (implemented via AjaxLink) that closes the panel and removes it from the list.
This is how the ListView is initalized and how the panels are created:
panelsList = new ArrayList<MyPanel>();
pnlContainer = new WebMarkupContainer("pnlContainer");
ListView<MyPanel> pnlItems = new ListView<MyPanel>("pnlItems", panelsList) {
#Override
protected void populateItem(final ListItem<MyPanel> item) {
item.add(item.getModelObject());
item.add(new AjaxLink<Void>("pnlClose") {
#Override
public void onClick(AjaxRequestTarget target) {
panelsList.remove(item.getModelObject());
target.add(pnlContainer); // repaint panel container
}
});
}
};
pnlContainer.setOutputMarkupId(true);
pnlContainer.add(pnlItems);
add(pnlContainer);
This works so far - the actions that trigger adding new panels (usually also AjaxLinks) do what they should and the new panel is added and displayed correctly. But I have problems getting the close button to fully work.
Please see the following steps:
1) I start the server and navigate to the main page. The ListView is initially populated with one panel.
Close-button-code of this panel:
<a wicket:id="pnlClose" id="pnlClose7" href="javascript:;">Close</a>
Searching the page code for pnlClose7 finds the following javascript code that makes the button work as expected:
Wicket.Ajax.ajax({"u":"./?0-1.IBehaviorListener.0-pnlContainer-pnlItems-0-pnlClose","e":"click","c":"pnlClose7"});;
Note: I do not press the button now, if i would, it would work as expected (thoroughly tested).
2) I trigger an action that opens a second panel. The panel is displayed below the first one as expected.
Close-button of the first panel:
<a wicket:id="pnlClose" id="pnlClosef" href="javascript:;">X</i></a>
Close-button of the second panel:
<a wicket:id="pnlClose" id="pnlClose10" href="javascript:;">X</i></a>
But now, neither searching for pnlClosef nor pnlClose10 finds some javascript code. The buttons (both!) do not work. I can still find the javascript code for pnlClose7.
3) I reload the page via pressing F5.
The button IDs change to pnlClose1a and pnlClose1b. Both IDs have javascript counterparts and work.
4) I press the first button (upper panel, ID pnlClose1a). The panel is closed as expected.
The remaining button's ID changes to pnlClose1c, again without a javascript counterpart. Javascript code for pnlClose1a and pnlClose1b is still present.
To make a long story short, the javascript handlers for my AjaxLinks seem to have shyness issues and only appear after I press F5 or reload the whole page in any other manner. I guess thats because repainting the pnlContainer changes the IDs of the current panels - but why is the linked javascript not updated at the same time? Is there anything I can change in my code to update the whole page without completely reloading it?
Wierd thing is that I am pretty sure this worked before... But I checked the whole class history and can't find any major change that would have triggered that. The ListView-code is mainly static since I added it.
I was had similiar problem. if you have any hardcoded javascript code in your page or panels html file (using <script> tag) remove it and set that js code in renderHead of your panel.

My panel not showing in Smart GWT

I am trying to add a GXT panel to my smartGWT tab panel but it is not showing.i get this error.i have done this in another tab and it is working but in in my second tab. when i select the second tab i see blank page and in the console i have this error.
Uncaught JavaScript exception [uncaught exception: java.lang.AssertionError: A widget that has an existing parent widget may not be added to the detach list] in , line 0
here is my code
VLayout formBtnFrm = new VLayout();
formBtnFrm.addMember(addEditForm);// addEditForm is DynamicForm
HLayout buttonLayout = new HLayout();
buttonLayout.setMembersMargin(10);
buttonLayout.setHeight(22);
buttonLayout.addMember(createUser);
buttonLayout.addMember(editUser);
buttonLayout.setLayoutAlign(Alignment.CENTER);
formBtnFrm.addMember(buttonLayout);
ContentPanel panel = new ContentPanel();
panel.setFrame(true);
panel.setCollapsible(false);
panel.setAnimCollapse(false);
panel.setButtonAlign(HorizontalAlignment.CENTER);
panel.setHeading("Registration Form");
panel.setLayout(new FitLayout());
panel.add(formBtnFrm);
panel.setSize(350, 250);
groupLayout.addMember(panel);
mainLayout.addMember(groupGrid);
mainLayout.addMember(groupLayout);
addMember(mainLayout);
As it is not recommended at all to mix (for example gwt and smartgwt) I guess it's same thing with Gxt widgets by expérience (with gwt mix) even if it happen to work you never know when you will have a crazy behavior..;
You can always mix GWT widgets with those of Smartgwt, but not Smartgwt and gxt. Chances are many that things might not workout as expected because these are on the same level, they are are all bulit on top of gwt. Meaning the two venders might not have concentrated on making their widgets feet into each other.

Nvigation within a GWT application

I intend to build a web application where users can enter their time every week and have been struggling to get my head around the concept of a single page in GWT that gets repainted with data depending on the user actions. After researching a lot on this site and google, I found one link that I would like to emulate but dont know how to go about doing it in GWT. Although their source code is available, I dont think it is full and complete. I got some idea from this link - Multiple pages tutorial in Google Web Toolkit (GWT) but again dont know how to implement it into a working version. One small working sample would be great to help me understand and get started.
Could anyone please guide me as to how to achieve the look and feel of the screen with the link below and how the content can be repainted with data from the server ? Would I need to put all the logic in one EntryPoint class ? I would like to have the hyperlinks in the left navigation panel and show the content in the right panel. I seem to be completely lost after a few hours of research.
http://gwt.google.com/samples/Showcase/Showcase.html#!CwHyperlink
Thanks a lot for your help.
Regards,
Sonu.
A single page application layout is actually quite easy to achieve.
The first thing you do is define the general layout, using GWTs layout panels. For your layout, I'd suggest using a DockLayoutPanel.
Content content = new Content();
Button switchContent = new Button(content);
Navigation navigation = new Navigation();
navigation.add(switchContent);
DockLayoutPanel pageLayout = new DockLayoutPanel(Unit.EM);
p.addWest(new HTML(navigation), 7.5);
p.add(new HTML(content));
Here, the width of the navigation panel will be fixed, whereas the content will take the remaining space. You have to pass a reference of the button (or some other widget) which does the switch of the content area, add the button to the navigation area, and so on.
Put this into a class, e.g. called MasterPageFactory:
public class MasterPageFactory {
private MasterPageFactory() {}
public static MasterPage newInstance() {
Content content = new Content();
Button switchContent = new Button(content);
Navigation navigation = new Navigation();
navigation.add(switchContent);
DockLayoutPanel masterPage = new DockLayoutPanel(Unit.EM);
masterPage.addWest(new HTML(navigation), 7.5);
masterPage.add(new HTML(content));
return masterPage;
}
}
Now, in your EntryPoint class, call the factory:
RootLayoutPanel.get().add(MasterPageFactory.newInstance());
This example should get you an idea. Other options would be using a DI framework like Guice or the Command pattern.
Your question is mixing up a couple of concepts. If you want the user to click something that looks like a link, and in reponse the application sends a request to the server and shows a page that looks different than the page they're on, and that page has fresh data that just came from the server, then you want a perfectly normal anchor or form submit button. You don't need anything special or weird from GWT.
The showcase example you referenced lets the user click something that looks like a link, and looks like it loads a new page, even to the point of letting the back button work as expected, but does not actually hit the server to get a new page or new data.

Problem with GWT TabPanel and Google Maps

Working with Google Web Toolkit (with Google Maps Extension) I got a little problem:
I want to insert a Google Map into a TabLayoutPanel. Without that TabLayoutPanel everything worked fine. But as soon as the Map is inside of a tab it behaves really strange (its not centered right, and "jumps" when you try to scroll.).
The same Problem is when using TabPanel instead of TabLayoutPanel.
extract from my code:
in the onModuleLoad - method of my EntryPoint class:
DockLayoutPanel mainPanel;
MainUITabs tabWidget = new MainUITabs();
mainPanel.add(tabWidget);
RootLayoutPanel.get().add(mainPanel);
the MainUITabsWiget looks about like that:
public class MainUITabs extends Composite {
public MainUITabs(){
TabLayoutPanel tabPanel = new TabLayoutPanel(10, Unit.PCT);
MapWidget googleMapsTab = buildMapWidget();
tabPanel.add(googleMapsTab, "Google Maps");
initWidget(tabPanel);
}
private MapWidget buildMapWidget() {
LatLng coord = LatLng.newInstance(51.509, 11.434);
final MapWidget map = new MapWidget(coord, 2);
map.setSize("600px", "300px");
map.setCenter(coord);
map.addControl(new LargeMapControl());
map.addOverlay(new Marker(coord));
return map;
}
}
Seems like the Map doesn't like to be inside a tab..does anyone have an idea where the problem could be?
Thanks.
Andy
The TabPanel docs say that "This widget will only work in quirks mode. If your application is in Standards Mode, use TabLayoutPanel instead."
So, if your page has a DOCTYPE and thus is in Standards Mode, that suggests you'll have problems.
I found that when using a TabPanel in Standards Mode, widgets on tabs after the first one (which aren't visible at first) don't always render correctly. A workaround was to render these elements when the tab is shown, by using SelectionHandler.onSelection, as noted in the docs for the deprecated method TabPanel#onTabSelected. But reading the bit I quoted above, that's probably asking for trouble and in Standards Mode you ought to use TabLayoutPanel instead.
At first glance this looks like a problem I had with integrating TinyMCE (a WYSIWYG editor) with GWT - generally, components like these don't like when the DOM changes - in this case, it happens when you switch tabs (in my case it was drag & drop).
IIRC, the solution was to remove the TinyMCE widget from the text field it wrapped around when it wasn't shown on the screen. In your case, you'd want to remove the MapWidget from tabPanel, while it's not shown. I'm not familiar enough with the Google Maps API to know if there's a designated method to do that, but you can try a simple tabPanel.remove(googleMapsTab);.

Adding Content to a GWT Horizontal Panel from another class

I am trying to populate the right-hand-side of a HorizontalPanel used in an onModuleLoad() method from another class (containing other widgets) so to keep the code separate.
What I am trying to achieve is similar to a PHP include where I can alter the code in another class and it will affect the right-hand panel only.
Does this other class have to be a composite widget? Or can I do a similar thing that I do when creating the Entry class?
I'm not sure if you mean you want to load a complete different GWT module on the right-hand panel or simply want to load a different class. I assume the latter.sense.
In such case a GWT TabPanel, but positioned Vertical. This is a combination of a DeckPanel and a TabBarPanel. In GWT there is standard VerticalTabPanel available, but you can find one in the open source cobogw library, see http://www.cobogw.org. An example including source code can be found on the demo page: http://cobogw.googlecode.com/svn/demo/WidgetsDemo.html#VerticalTabPanel
The example also uses a LazyPanel. This means each class is initialized only when the user clicks on the link, which makes startup a lot faster.
Just add the reference to the horizontalpanel to some other class (like a controller class or main panel class) and then call into this class from your right side panel. You can even have a controller class that holds this static horizontalpanel with a method like
HorizontalPanel hPanel; //set this from on module load, or controller.create method for instance
public static setRightContents(Panel panel){
hPanel.add(panel)
}
and just call this from the other class Controller.setRightContents(myNewRightPanel).
Really you just need to stop thinking this is a website and start thinking more of a thick client application using even driven programming.