Hi Freddy,
I recognize this problem and don't think its straightforward to solve
without a bit of coding.
Here are some issues that I've encountered using Ajax together with
Click controls:
1. As you've described the control and JavaScript/CSS resources have
to be streamed back to the browser. Below I've included a snippet
which can be used to solve this [1].
2. On the client side there must be a way to include JavaScript and
CSS resources only once. Otherwise a memory leak occurs when the same
resources are included again and again. On the server side this is
solved using PageImports, but Click does not include support for the
client side.
3. Extending from #2, if a JavaScript resource (<script src="...") is
included via Ajax, the browser will load the resource from the server.
If the same JavaScript resource is included a second time the browser
will load the resource again. This second call to the server is
redundant because the resource is already available to the browser. (I
dont't remember if this is true for both CSS and JavaScript but I do
recall seeing this behavior for JS at least)
4. When replacing DOM elements in the browser, one must ensure that
any registered JavaScript events on the old DOM elements, must be
re-registered on the new elements. For example say you have a link
(<a>) that when clicked will update itself. The link obviously has a
click event registered. But when the link is replaced by Ajax, the
click event must be registered again. Fortunately JavaScript libraries
are starting to support this without having to re-register the event.
For example JQuery has the LiveQuery plugin and the new live() event
system.
There is also the ClickClick-JQuery project which solves the issues
outlined above so it might be worth checking out.
Let us know if you have any thoughts on solving this in a cleaner way.
kind regards
bob
[1]:
public class AjaxPage extends BasePage {
public void renderControl(Control control) {
Context context = getContext();
HttpServletResponse response = context.getResponse().write(...);
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
// Handle deprecated htmlImports
String imports = control.getHtmlImports();
writer.println(imports);
// Handle new head elements
List elements = control.getHeadElements();
for(...) {
writer.println(element);
}
// Write out control
writer.println(control);
// Setting path to null informs ClickServlet that Page template
should not be rendered
setPath(null);
}
}
Freddy Daoud wrote:
Hi gang,
I'm trying out a basic Ajax example.
I have an abstract BasePage with a layout.htm reusable template, with
HTML boilerplate, $cssImports, $jsImports, #parse($path) to include
the concrete page's content.
I have a HomePage that extends BasePage and a home.htm template that
just includes the content for the page, e.g. $table.
So far so good.
Now, say I want to load the HomePage with an Ajax request. I issue the
request and in BasePage#getTemplate(), I return getPath() instead of
layout.htm if it is an Ajax request.
This works beautifully! Except....that because the initial page
doesn't have a Table in it, the $*Imports don't include the CSS that
Table needs. When the Ajax request is issued, the response is only the
home.htm block, not the whole page, so the Table doesn't get to
contribute its imports to the page.
I can add an #if in home.htm to add $*Imports for an Ajax request, but
this is a hack and also repeats any imports that are common to the
initial page and to the home page.
Is there a cleaner solution to this problem?
PS context.isAjaxRequest() => nice touch :)
Thanks in advance for your help!
Freddy