Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Wednesday, February 28, 2007

Screencast #5: Grid Component

The latest Tapestry 5 Screencast is now ready; this one clocks in at almost 11 minutes, and shows me forgetting parameter names and such as I set up a grid with my good ole' fallback: iTunes music data. I actually made a couple of mistakes on purpose to show off the exception reporting (that's only gotten better since 5.0.2, the base line for this screencast).

I think this shows off how quickly and easily you can pull data out of a service and up on the screen. To borrow a phrase: "I don't have time for drag and drop!"

One minor mistake was that I didn't map the context correctly (I had cut-n-pasted an existing launch configuration); thus all the URLs are prefixed with "hilo/" rather than, say, "musiclib/". Oh well. Oops, and I forgot to hide the dock!


Jacob Hookom said...

to a point, do you think that if nothing visual is gained by doing <table t:comp="grid" when there is no nested dummy data, to introduce the convention used with JSP/ASP/CF/etc and simply allow <t:grid or <t:outputRating?

sicklittlemonkey said...

Howard, you need to edit your post "I think this shows off how quickly and easily" ... what?

(You can moderate this comment out since I'm just pointing out an error.)

Anyway, great work. We are considering jumping straight from T3 to T5!


Howard said...

I've been thinking about <t:grid>, etc. I'e been deciding what to do when the component in question is inside a folder, i.e., <t:comp type="ajax/Whizzbang"> ... maybe <t:ajax.Whizzbang> ? It does seem like the best way to leverage the namespace concept.

I think I will eventually want to narrow down the possibilities; so if <t:grid> gets added as an option, then <t:comp> should be ditched. I think <table t:type="grid"> is here to stay.

Jacob Hookom said...

for what will be 3rd party components, would you need full FQCN to find the appropriate component to insert in every instance? I like the idea of binding namespaces such that:

<html m:xmlns="com.company.components" ...>
<m:foo source="bean.name"/>
<m:sub.widget var="bar"/>

Robert J. Walker said...

(Feel free to moderate out this comment.)

Could you change your blog style sheet so that you can actually distinguish links from the surrounding text? Every time you link to something in your posts (like this one), my first reaction is always, "Where's the link? Oh, yeah, I have to scrub the text for it."

Fortunately, your blog is "muy excelente," so that compensates for the minor CSS gripe. :)

D&J said...

Very nice, Howard. The really tricky part is going to be making it flexible enough for the more advanced use cases out there, but it looks like you're on the right track.

One thing that struck me as odd, given T5's emphasis on convention and reducing LOC, was the need to declare an unused _currentTrack instance variable in the page. Could you have referred directly to grid's row property from within the template?

Howard said...


To some degree, you could reference the Grid's row property, but then you'd have to create a getter method for the Grid component itself. Further, the type of the Grid's row property is java.lang.Object, so you would not be able to de-reference properties through it (such as the Track's rating property). So, creating the property serves two purposes: access to the value, and nails down the type of the value (as in, Track).


Although there aren't third party libraries yet, the mechanism is in place. You can "mount" a virtual folder to a package, to reference pages and components within those packages. Thus, we may mount "ajax/" as "org.apache.tapestry.ajaxlib" and reference component org.apache.tapestry.ajaxlib.components.Whizbang as "ajax/whizbang". The "mounting" is by a contribution to a service's configuration ... and given Tapestry 5 IOC's dynamic locating and loading of modules, this means that having the ajaxlib.jar on the classpath is all that's necessary to start referencing and using those components. Zero configuration is the way to go.

Luis Ramirez said...

Howard congrats for such a good work, T5 is getting better and better. Anyhow I'd like you to publish a T5-Spring integration screen cast, or at least if you could point me out where could i found that, I've been digging into the documentation but have never found something tangible in that matter. We've got a lot of Spring usage so it is our primary concern.

Thank you in advance, and keep with that nice work, the grid component is killer!

Howard said...

Just becuase I haven't written the tapestry-spring integration is no excuse, I guess :-)

钢轶 said...

nice work!!!
But, can I hide a column in the templete instead of in the model class? Maybe someone don't want to add tapestry annotation to his entity classes.

Mst Tap said...

I think the Grid components is excellent. Using it and adding actionlinks is easy.

However, a solution to a very common situation is unclear to me: I have a Grid component, actionlinks on every row, as well as some (text areas and drop-down boxes) other fields and a few submit-buttons outside the Grid, but inside the Form. A bit like Gmail or Yahoo mail without the frills.

I would also like to put a checkbox beside the other row data in the Grid. (again, just like webmail). I could easily add a checkbox beside each row which would just display the boolean data in the row-data object "behind" it.

However, I don't know how to just add a checkbox to every row so I can select one or more rows that have to be processed simultaneously upon clicking one of the submit buttons. These boxes aren't really there to reflect data in the data object behind the row because they just are there to help identify rows in the context of the form processing of that particular page.

I suspect there is some way to put a "model" "behind" the form, purely to hold data within the context of processing that form.

Given the excellent design of Tapestry 5, I believe there must be some way to do all of this cleanly. But even if the solution would to be a bit messy, I still would to know about it.

scott said...

First let me say thanks for the tutorials you've done, very helpful. I am new to tapestry, your screencasts are easy to follow and easier to grasp then say docs. Question: I would like to know/see the library service class you created/used in the screencast5. Specifically: MusicLibray.getTracks(). I realize that it is not the focus but I am trying to dup the example. I created a bogus datasource class attempting to simulate your class but this gets me errors:

# java.lang.RuntimeException
java.lang.ClassNotFoundException: caught an exception while obtaining a class file for org.example.hilo.pages.Start
# java.lang.ClassNotFoundException
caught an exception while obtaining a class file for org.example.hilo.pages.Start

java.lang.RuntimeException: Error obtaining injected value for field org.example.hilo.pages.Start.dsource: No service implements the interface org.example.hilo.pages.DataSource.

# java.lang.RuntimeException
Error obtaining injected value for field org.example.hilo.pages.Start.dsource: No service implements the interface org.example.hilo.pages.DataSource.

public class DataSource {

public List (SampleData) getData() {
List(SampleData) list = new ArrayList(SampleData)();
for (int i = 0; i < 100; i++) {
SampleData sd = new SampleData();
sd.setColor(i + "color");
sd.setName(i + "name");
sd.setSize(i + "size");
return list;
open close tags are replaced with ()s.
Thanks for any further explanation.

Howard said...


You need to define your DataSource as a service inside Tapestry IoC. It then becomes visible for injection into components.

Some of this is already in the tutorial, and you can get more details by examining the Tapestry integration tests.

Further questions to users@tapestry.apache.org, please.

Javer said...

I agree with Mst Tap, grid component is very nice to use, but there should be some support to handle checkboxes inside it. (Example: select 34 rows to delete with one form submit)

I managed to create a component in Tapestry 4 to handle this, but I still don´t know how to do it with T5.