This week's book giveaway is in the OCMJEA forum.
We're giving away four copies of OCM Java EE 6 Enterprise Architect Exam Guide and have Paul Allen & Joseph Bambara on-line!
See this thread for details.
The moose likes JSF and the fly likes Simple loop/function in XHTML page Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCM Java EE 6 Enterprise Architect Exam Guide this week in the OCMJEA forum!
JavaRanch » Java Forums » Java » JSF
Bookmark "Simple loop/function in XHTML page" Watch "Simple loop/function in XHTML page" New topic
Author

Simple loop/function in XHTML page

André Stein
Greenhorn

Joined: Feb 20, 2009
Posts: 4
Hi there.

I built a pretty complex XHTML page for/with Seam. There are two paragraphs that are pretty much the same, except for small differences. I'd like to put this duplicated code in some kind of loop and parameterize this with "1" and "2" (so there would be just 2 cycles). What's the best way to do this?
I already experimented with some things and found out the following:

- <ui:repeat> basically allows me to do what i want, but I would need to put some kind of simple String array containing "1" and "2". One optin would be to create a stupid method on any of my components that returns this array, but it seems to be not the best option. Basically I would just need an array containing "1" and "2" right before executing this ui:repeat. Is there a way to do this via expression language?

- <a4j:repeat> is pretty much the same like ui:repeat, seems to be a good thing, but for example asking "stateVar" for its current value always returns 0 when running through some list. I thought this was some kind of loop counter?

It there any other way to execute some lines of XHTML-code multiple times (in my case just two times) with giving the whole thing a parameter that increases every time the code is run? Something like "execute the follwoing code <2> times and replace any occurence of <i> with the loop counter"? I would guess it's not that hard, but I couldn't figure out how to do it until now... :-(

Thanks and greetings,
--
André
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16022
    
  20

Welcome to the JavaRanch, André!

Since you're new here, you probably haven't seen any of my rants as to why putting logic in a View is a Bad Thing. But it is.

On the other hand, I'm not sure what you really want is true iteration, so much as to repeat a sub-view with variations. I'm presently working on an app that has no less than 4 such items on a page.

Actually, before I proceed, it's pretty obvious that you're not really talking about xhtml, you're talking about Facelets.

Because the number of sub-views is fixed on my page, I construct them as follows. As you can see, I'm passing parameters to the Facelets framework to allow it to customize the sub-views it constructs.



Customer surveys are for companies who didn't pay proper attention to begin with.
André Stein
Greenhorn

Joined: Feb 20, 2009
Posts: 4
Hi Tim.

Thanks for your explainations. Your solution sounds interesting, I think I'll try it. But actually I'm not putting any logic in the view, it's just that I have two nearly identic parts of code and want to minimally parameterize the execution to avoid code duplication...
In the meantime, I built a backend method that returns an array containing "1" and "2" and I created a loop with ui:repeat and it basically works. But I'll try your way of doing this, sounds much more elegant... ;-)
Currently I'm stuck at another problem with the EL. I want to display different things from a messages-property-file for different parameters of the run, some kind of "nested EL", but it just doesn't work. Here's what I'm trying to do:

<h:outputText value="#{messages['main.selection<<<parameter>>>.title']}" />
(<<<parameter>>> is later, at runtime either "1" or "2", in the examples below called "i")

I tried:
value="#{messages['main.selection#{i}.title']}"
value="#{messages['main.selection{i}.title']}"
value="#{messages['main.selection'.i.'.title']}" (dot for String concatenation?)
value="#{messages['main.selection'.{i}.'.title']}"
value="#{messages['main.selection'.#{i}.'.title']}"

Just can't tell the EL to first resolve the parameter "i" and then look up the message... :-(
You have any idea how this could work?

Thanks,
--
André
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16022
    
  20

Sometimes I misread stuff unless I print it out, but what it looks like to me is this:

(parent xhtml)



(included xhtml)



I'm assuming that your messages are defined in the backing bean as "Map<String, String>[2] myMessages"
André Stein
Greenhorn

Joined: Feb 20, 2009
Posts: 4
For the messages, I use the standard-way of Seam, I haven't implemented anything especially for this, I just use the "messages.properties"-file.
I'll take your example as a basis for my problem:


I have the "loop-counter"/parameter "i" and in the messages-defintion, there are messages named "main.selection1.title" and "main.selection2.title". I want to parameterize the call of these messages by doing something like "main.selection#{i}.title". This whole expression itself should be there where you put "title" in your example, so I image something like this:



But this doesn't work as the expression language doesn't seem to allow nested expressions...
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16022
    
  20

fair warning: complex EL expressions can be a major pain. For one thing, since most of the work is done via abstract binary generic mechanisms, it's a thankless task to try and run one through a debugger. That's one reason why I abstracted my stuff out into 2 parts.

However, I think what you want is probably closer to this:

value="#{messages['main.selection'].title']}"

You'd be far better off pushing as much of that stuff into your backing bean, however. It will save a lot of time you'd otherwise spend fighting the EL syntax and semantics. I've decently competent in EL, and even [i]I
would hate to try and construct an EL expression like that.

If you can even compact it down to something like:

value="#{backingBrean.mainSelectionMessage[i].title}"

You'll have less grief. Plus you can set a debugger breakpoint on the getMainSelection(int index) method and see what's actually going to be used as the basis for the data reference.
Marta Gb
Greenhorn

Joined: Feb 23, 2011
Posts: 3
Hi,

did you get a solution?

Thanks!
André Stein
Greenhorn

Joined: Feb 20, 2009
Posts: 4
I think the solution was more or less something like this. It's not exactly the code we're using because I can't find the code lines right now, but I think you'll get the clue:



So, i pulled out the first part of the substitution and used a variable for this intermediate result. Then I used this variable and put it into the second line. The parser sees that "foo" is a defined variable and uses its value. I think the trick was to use "foo" here, not "$foo" or "#{foo}". Maybe you also have to experiment a bit with the quotes here to make it working, but basically, that was our solution...

Hope that helps, bye.
--
André
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16022
    
  20

I don't recommend using JSTL on JSF pages. It can bite you.

Anything that looks like a variable name in a "#{}" expression will be resolved as a variable. If you want a literal value instead, wrap it in single quotes like so:

 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Simple loop/function in XHTML page