Sunday, February 27, 2005

Mixed Table Columns

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


Before I begin: Creator Update 7 is out. This is a pretty small patch (from update 6) containing just a handful of bugfixes - but some of them are important, so do update.



Anyway, I just browsed the Creator forum and saw a couple of questions I thought would make an interesting blog entry. Here's the
first question:


I would like to selectively have some items in the datatable be links and others not (e.g. some as simple outputtext, others as links). I need to make this decision at run time.


Is this possible to do? Is there an event to dynamically alter the table item output?



Yes, it's possible - with a little trick! You cannot change the types of components, but you -can- dynamically control whether a component is visible or not! Therefore, all you need to do is place BOTH types of components in the column, create a property which determines which type of output you want for the current row, and then cause exactly one of the two components to be made visible for this row. You control component visibility with the "rendered" property of a JSF component.



Let's take a specific example. I drop a Data Table component on the canvas, and then I drop the "PERSON" table from the Sample "Travel" database that ships with Creator. It has 4 columns: Id, Name, Jobtitle, and FrequentFlyer. I want to make the Name column use a hyperlink if that person is a Frequent Flyer. To do this, I drag a hyperlink and drop it in the Application Outline on top of "Column2" - this places the hyperlink in the second column in the table - the Name column.






Then I double click on the canvas to go to the Page bean for this file (the Java code) and add the following method to create a read-only boolean property:


public boolean isFrequentFlyer() {
Object o = getValue("#{currentRow['FREQUENTFLYER']}");
return o instanceof Boolean && ((Boolean)o).booleanValue();
}

Go back to the Page1.jsp file.



Finally, I go and update the value bindings:


  • I right click in the Application Outline on the new linkAction1 (make sure you don't select linkActionText, its child) and select Property Bindings.... In the dialog, choose the "Advanced" toggle button, and in the list on the left locate and select the "Rendered" property. In the list on the right, drill down to your page, and select the "frequentFlyer" property. Hit Apply, then Close.
  • Select the old output text component (this is the first output text in the table column in the application outline) and select Property Bindings. Again choose the frequentFlyer property for the advanced "Render" property. But before you hit Apply, edit it to be the logical opposite: change the binding expression from #{Page1.frequentFlyer} to #{not Page1.frequentFlyer}.
  • Select the text output inside the link, linkAction1Text, and bind its value property to the same as the original text - you want the link to say the same thing that the output text does, not "Link Action" as it does now. E.g. set its value to #{currentRow['NAME']}.

When you run, you should see this:






Notice how the hyperlinks are only showing up when the FrequentFlyer value is true. And of course there's no reason you need to show the frequent flyer column in the table - you can hide it with the Table Layout context menu item on the table. And furthermore, you can obviously make the logic for deciding which type to use as complex as you want - your isFrequentFlyer() method can do anything you want.


2 comments:

  1. Very useful stuff. I did not know how to do this, and I needed it.
    Thank you!
    ~Luis

    ReplyDelete
  2. It would be nice if the hyperlink component allows the disabled view. So that if you set it to true, it will not get displayed as link, but just text. What you described is a nice trick, but it's a hack, and a waste of resource on the JSF part (nothing to do with your suggestion, its JSF's problem).
    Your suggestion is certainly very useful for other type of mixing between components though.

    ReplyDelete