tags:

views:

6180

answers:

15

What's the best way to externalize large quantities of HTML in a GWT app? We have a rather complicated GWT app of about 30 "pages"; each page has a sort of guide at the bottom that is several paragraphs of HTML markup. I'd like to externalize the HTML so that it can remain as "unescaped" as possible.

I know and understand how to use property files in GWT; that's certainly better than embedding the content in Java classes, but still kind of ugly for HTML (you need to backslashify everything, as well as escape quotes, etc.)

Normally this is the kind of thing you would put in a JSP, but I don't see any equivalent to that in GWT. I'm considering just writing a widget that will simply fetch the content from html files on the server and then add the text to an HTML widget. But it seems there ought to be a simpler way.

+5  A: 

You can use some templating mechanism. Try FreeMarker or Velocity templates. You'll be having your HTML in files that will be retrieved by templating libraries. These files can be named with proper extensions, e.g. .html, .css, .js obsearvable on their own.

Boris Pavlović
Because the whole point of GWT is to write clientside apps. There is no need to go to the server to fetch this html. In a lesser environment one would use an iframe etc. but GWT lets you generate different js sensitive to your locale with strings containing html resources etc. The answer is Client Bundles as mentioned below.
mP
+1  A: 

You could try implementing a Generator to load external HTML from a file at compile time and build a class that emits it. There doesn't seem to be too much help online for creating generators but here's a post to the GWT group that might get you started: GWT group on groups.google.com.

Steve Reed
+1  A: 

I was doing similar research and, so far, I see that the best way to approach this problem is via the DeclarativeUI or UriBind. Unfortunately it still in incubator, so we need to work around the problem.

I solve it in couple of different ways:

  1. Active overlay, i.e.: you create your standard HTML/CSS and inject the GET code via <script> tag. Everywhere you need to access an element from GWT code you write something like this:

    RootPanel.get("element-name").setVisible(false);
    
  2. You write your code 100% GWT and then, if a big HTML chunk is needed, you bring it to the client either via IFRAME or via AJAX and then inject it via HTML panel like this:

    String html = "<div id='one' "
       + "style='border:3px dotted blue;'>"
       + "</div><div id='two' "
       + "style='border:3px dotted green;'"
       + "></div>";
    HTMLPanel panel = new HTMLPanel(html);
    panel.setSize("200px", "120px");
    panel.addStyleName("demo-panel");
    panel.add(new Button("Do Nothing"), "one");
    panel.add(new TextBox(), "two");
    RootPanel.get("demo").add(panel);
    
IgorM
The issue isn't what widget to use for HTML data; the issue is how to get the HTML *out* of the code, and into something more natural like a .html file.
Limbic System
Yep. The example above is not to show how to put the HTML into the code, but merely to show that you can reference HTML that is residing outside of your code that can be packaged in multiple ways. In the example above it was a string. In the same way you can reference the external files via URL.
IgorM
Put the HTML into a file (*.html if you want), load the file on the server and use the HTMLPanel() to display the content.
Aaron Digulla
+3  A: 

I'd say you load the external html through a Frame.

Frame frame = new Frame();
frame.setUrl(GWT.getModuleBase() + getCurrentPageHelp());
add(frame);

You can arrange some convention or lookup for the getCurrentPageHelp() to return the appropriate path (eg: /manuals/myPage/help.html)

Here's an example of frame in action.

Miguel Ping
A: 

Not knowing GWT, but can't you define and anchor div tag in your app html then perform a get against the HTML files that you need, and append to the div? How different would this be from a micro-template?

UPDATE:

I just found this nice jQuery plugin in an answer to another StackOverflow question.

David Robbins
The questioner wishes to avoid the round trip to fetch the html. Basically they want to embed the escaped pages as a String within the app automatically aka using ClientBundle.
mP
A: 

You can use servlets with jsps for the html parts of the page and still include the javascript needed to run the gwt app on the page.

harmanjd
A: 

Why not to use good-old IFRAME? Just create an iFrame where you wish to put a hint and change its location when GWT 'page' changes.

Advantages:

  • Hits are stored in separate maintainable HTML files of any structure
  • AJAX-style loading with no coding at all on server side
  • If needed, application could still interact with loaded info

Disadvantages:

  • Each hint file should have link to shared CSS for common look-and-feel
  • Hard to internationalize

To make this approach a bit better, you might handle loading errors and redirect to default language/topic on 404 errors. So, search priority will be like that:

  1. Current topic for current language
  2. Current topic for default language
  3. Default topic for current language
  4. Default error page

I think it's quite easy to create such GWT component to incorporate iFrame interactions

Alexander Kosenkov
So, you might have such file structure on your server:/help/welcome/en.html or /help/welcome-en.htmlthis page will contain english text for topic or GWT-page 'welcome'
Alexander Kosenkov
Because GWT supports creating classses with getters that include html with parameters from html files. It also supports fetching generating different permutations of your program each with different html based on a locale. If you thought of it, its been done better in GWT.
mP
+1  A: 

GWT 2.0, when released, should have a ClientBundle, which probably tackles this need.

Tomer
+1  A: 

The GWT Portlets framework (http://code.google.com/p/gwtportlets/) includes a WebAppContentPortlet. This serves up any content from your web app (static HTML, JSPs etc.). You can put it on a page with additional functionality in other Portlets and everything is fetched with a single async call when the page loads.

Have a look at the source for WebAppContentPortlet and WebAppContentDataProvider to see how it is done or try using the framework itself. Here are the relevant bits of source:

WebAppContentPortlet (client side)

((HasHTML)getWidget()).setHTML(html == null ? "<i>Web App Content</i>" : html);

WebAppContentDataProvider (server side):

HttpServletRequest servletRequest = req.getServletRequest();
String path = f.path.startsWith("/") ? f.path : "/" + f.path;
RequestDispatcher rd = servletRequest.getRequestDispatcher(path);
BufferedResponse res = new BufferedResponse(req.getServletResponse());
try {
   rd.include(servletRequest, res);
   res.getWriter().flush();
   f.html = new String(res.toByteArray(), res.getCharacterEncoding());
} catch (Exception e) {
   log.error("Error including '" + path + "': " + e, e);
   f.html = "Error including '" + path +
        "'<br>(see server log for details)";
}
David Tinker
A: 

I'm not sure I understand your question, but I'm going to assume you've factored out this common summary into it's own widget. If so, the problem is that you don't like the ugly way of embedding HTML into the Java code.

GWT 2.0 has UiBinder, which allows you to define the GUI in raw HTMLish template, and you can inject values into the template from the Java world. Read through the dev guide and it gives a pretty good outline.

Steve Armstrong
A: 

You can try gwtapp.org with html templates generated and binded on run-time, no compiling-time.

trex
A: 

@Limbic System - I have exactly this issue of integrating large number of static HTML pages into my GWT app. I have evaluated IFrame approach where I can set the url of the html file that I need to load. But I wasn't quite happy with the results. So how did you finally tackle this scenario? Could you please share?

jch
A: 

I've used ClientBundle in a similar setting. I've created a package my.resources and put my HTML document and the following class there:

package my.resources;

import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.TextResource;

public interface MyHtmlResources extends ClientBundle {
 public static final MyHtmlResources INSTANCE = GWT.create(MyHtmlResources.class);

 @Source("intro.html")
 public TextResource getIntroHtml();

}

Then I get the content of that file by calling the following from my GWT client code:

HTML htmlPanel = new HTML();
String html = MyHtmlResources.INSTANCE.getIntroHtml().getText();
htmlPanel.setHTML(html);

See http://code.google.com/webtoolkit/doc/latest/DevGuideClientBundle.html for further information.

Futzilogik