Monday, November 20, 2006

Clever Title Using The Word "Fragments"

Sometimes it happens that you want a page to allow for a very small variation in markup based on something that happens at runtime. For example, you might want to include just a simple phrase like "No items found" in the case that nothing was found, or some more complex markup in the case that you had something to show. Or in my case, it's desired to conditionally include an <img> tag should the poster have a PNG file containing a mugshot stored on the local filesystem, or to include an ad panel if one has been requested but leave the space blank otherwise.

Without fragments, the only way to have conditional markup where the contents of that markup are manipulated by wicket would be to have multiple classes and multiple markup files. That's a lot of work for an insignificant difference in the content of the page. Wicket provides, however, and we have a construct like this:

<span wicket:id="mugshot">(mugshot)</span>

<wicket:fragment wicket:id="hasMugshot">
<img src="/images/posters/Gorthak.png" alt="[Gorthak mugshot]" class="mugshot" wicket:id="mug" />
</wicket:fragment>


In the code we can say something like this:

if (mugPath != null) {
Fragment mugfrag = new Fragment("mugshot", "hasMugshot");
mugfrag.add(new Label("mug", "") {

private static final long serialVersionUID = 1L;

@Override
protected void onComponentTag(ComponentTag tag) {

System.out.println("onComponentTag called!");
tag.getAttributes().remove("src");
tag.getAttributes().add("src", mugPath);
tag.getAttributes().remove("alt");
tag.getAttributes().add("alt", mugUser + " mugshot");
}
});
add(mugfrag);
} else {
add(new Label("mugshot","").setEnabled(false));
}


Now I probably could have accomplished something similar in this simple case by just setting up the img tag with a wicket:id and setting that element visible or invisible. Notice what the fragment lets us do, however- something we can't do with plain markup in Wicket. We can ignore the fragment completely in the Java code (as in the else block above). Similarly, we can conditionally use one <wicket:fragment> from an arbitrary number of them if we choose.

One thing to keep in mind is that when you're adding components in the Java class that are encapsulated by a <wicket:fragment>, you're adding them to a Fragment not to the page. As you can see, adding a Fragment involves giving the name of the place you want the wicket:fragment to go and the name of the fragment itself.

You can see I'm doing some crazy inner-class trickery for my img tag. Wicket's Image class expects to refer to an image file that's contained within the framework. In my case, the image is actually out on the filesystem as part of the static content of the web site. So I've basically extended the Label class to deal with the needs of an img tag, in this case replacing the contents of the src and alt attributes when the tag is rendered. I'll probably refactor this out into its own class at some point- there's really more code than I'd like to see in an anonymous inner class there, and I could see reusing it in other places.

Another thing I want to work on is a strategy for copying in/out values from the data model to the service bean classes. I'm thinking that annotations+reflection might be an effective and clean way of doing it.

I resolved my earlier pondering about the article table trigger in PostgreSQL. It is as simple as this:

ELSIF (TG_OP = 'UPDATE') THEN
IF (NEW.section != OLD.section OR
NEW.title != OLD.title OR
NEW.adjective != OLD.adjective OR
NEW.summary != OLD.summary OR
NEW.body != OLD.body) THEN
INSERT INTO article_audit SELECT nextval('article_audit_audit_id_seq'), now(), 'U', NEW.*;
END IF;
RETURN NEW;


Duck soup!

Labels:


Comments:
Hi Nick.

Thanks for the useful code here for managing images. I tried this out and had some problem with the image not loading. In my case, I'm referring to an image out on the internet, and if I don't pre-load this image in another browser window, I just get the alt text from my wicket markup.

It appears to me like some sort of caching issue.

Have you any pointers to help me out?

Thanks.
 
My only advice is to take a look at the ExternalImage class I ended up making, which you can find here:

http://tally-ho.googlecode.com/svn/trunk/net.spatula.news/src/java/net/spatula/tally_ho/ui/ExternalImage.java

And also to look in the generated page source to see if the way the img tag gets produced seems to make sense.
 
Post a Comment





<< Home

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]