• Post Reply Bookmark Topic Watch Topic
  • New Topic

Primefaces, creating custom Tabs in TabView

 
Vasilis Souvatzis
Ranch Hand
Posts: 81
1
Chrome Java Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good morning fellow Ranchers! Today I would like some help on how to use a Primefaces TabView for input. Let me explain.

I have found this link that implements the behaviour of the TabView. It basically says to make my own Tab model.


But I want each tab to contain something like this:



I tried adding the inputTexts in my Tab model but it doesn't work, I guess I was way too optimistic :P

The only reason I want this is because I don't know how many tabs I need. It's totally dynamic, the number of Lectures is added on demand.
 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're probably going to have use a JSF tag binding on your tab container.

I haven't heard many people using binding lately - which is good, since they were mis-using it all over the place, but then binding attribute is expressly designed for problems such as yours.

Basically, what a binding does is inject the actual control into your backing bean, making it available for dynamic modification. You can alter the control's properties and add or remove sub-controls (children).

Since what you want is fairly common, you should check the PrimeFaces documentation. They may have an example you can use.
 
Vasilis Souvatzis
Ranch Hand
Posts: 81
1
Chrome Java Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Awesome, thanks a lot Tim!

At first I looked into composite components but it seemed too much of a hassle for what I want to do. Since you say binding suits me I'll look into that at once, I found the pages in the EE 7 Tutorial.

For some reason I always forget about the Duke's Case Studies, I'll if they have something similar there.

Again, thanks a bunch :)
 
Vasilis Souvatzis
Ranch Hand
Posts: 81
1
Chrome Java Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And I'm back :)

Are there any "advanced" resources on binding, manipulating components and such? Since my issue isn't really Primefaces related, I'd like to look at examples with JSF component binding. The JavaEE 7 Tutorial doesn't have anything on component binding, unless I've missed it entirely...

For the time being I've set my project to work with static tabs, but I'll rewrite at some later point.
 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have an ancient book by Kito Mann on JSF that kind of addresses these things. Haven't read Geary, so I don't know what was said there and I don't even know what's newer - the disadvantage of no longer having physical bookstores around with actual browsable shelves of computer technical books.

The concept of binding is pretty straightforward. Each of the JSF tags has an associated UIComponent class. So, for example, "h:inputText" would be backed by UIHtmInput (if I remember the name properly).

The only tricky parts here are that in JSF2, these classes don't directly access the control's value (the "value" attribute is actually an EL expression just like in the xhtml) and the other attributes are not POJO bean attributes, but rather a collection within the bean. For convenience and/or history, some of this data has multiple access routes.

The UIComponents are elements in the UI component tree, meaning that there's a definite parent/child, 1-to-many relation and a "get children" method that allows access to the element's children collection. So what you'd be doing is adding or removing child UIComponents from the parent UIComponent (tab container). You can instantiate child components in the usual way - they all have no-element constructors, so to put a UIHtmlOutputText in a tab, you'd simply do a "new UIHtmlOutputText();", set the desired attribures, then add the new component to the tab element.

You can find any UIComponent via a brute-force search of the Component tree, but binding eliminates all that work, plus reduces the amount of code that's hard-coded to a specific component tree. The binding method is passed the element's corresponding UIComponent object, which you can then cache and play with.



 
Vasilis Souvatzis
Ranch Hand
Posts: 81
1
Chrome Java Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have found a couple more books about JSF but after skimming through their contents, I'm not sure how much they touch binding with examples.

I did exactly what you describe, having bound the UIComponent and adding children to it. Obviously I was doing something wrong because it didn't work, but I think I have the idea correctly. Your explanation here clarified some things as well.

Over at the Primefaces forum I was told that I can't use binding and declaratively creating components in the same parent. I should use Application in order to create them and not new. Maybe having a method that returns the component and not a void one adding the children?

I don't know, like I said I'll leave this issue alone for now. I'll revisit it at some point because it's quite important, I want to read up on JSF some more.
 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm not sure what they meant in the PrimeFaces forum. If you do a Binding to a component, that simply injects the bound component into the backing bean. If you declared children (using xhtml) underneath that component, you can use the component APIs to modify or delete those children, re-arrange their locations, and/or add/remove your own children. JSF doesn't care at that stage whether a given child was created via declaration or dynamic logic. A child is a child.

I think my public Subversion archive is offline at the moment - I've been reworking some of my infrastructure VMs. But here's an excerpt from the one and only JSF program I have that used binding. It's a generic database table editor, so it dynamically constructs a set of elements for the editing of each column in a selected database table row. This particular function creates a sub-component that contains a captioned checkbox and returns it to a parent function which will add it to the containing UIComponent. Note that the "cbox" component in turn has children constructed and added under it.



Note the "resolveExpression" magic. That's because the value of an HtmlInputControl is expressed as EL, not as a direct property value. Unlike onChange, which is straight JavaScript text. Remember, this isn't using the control, it's building it up to be rendered and output for a subsequent form submit.
 
Vasilis Souvatzis
Ranch Hand
Posts: 81
1
Chrome Java Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow! This is really interesting! This code snippet helps me a lot, thank you very much!

Seeing this code now, I understand I did the basics correctly but not overall. Hmmm, I'll do some testing and see what's going on.

Quite offtopic but at the beginning I chose Primefaces because it had ready-to-use custom components. With your code, I understand it's really easy to construct your own vanilla JSF components anyway hehe.
 
Vasilis Souvatzis
Ranch Hand
Posts: 81
1
Chrome Java Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well I'll be damned, I freaking did it! I FREAKING DID IT!

I think the problems occurred on three places, CDI beans, View tags and Scope of the bean. Here's what I did in a test project and works like a charm (lots of dumb code but it's for testing anyway). Not sure if all of them combined fixed the problem or individually.





In my main project (where I couldn't work out the adding new tabs), it was a CDI bean (annotated with Named) that was trying to add tabs. Maybe the Managed bean worked eventually because it's essentially "bound" to the view? And should have made a ManagedBean to add the new tabs, and then the CDI one to get the values and do further processing?

Also, the scope of the CDI bean was at Request I think (don't have my main project in front of me, can't be sure). Now that i have a ViewScoped bean it adds tabs all the time, not just once for the single request to the server.

Finally, I must had messed up the tags and attributes in the xhtml. I think I was trying to do stuff with value and var.

Truly finally, the first part of this "adventure" is complete. All I have to do now is add value expressions (like you showed on your snippet) so I can get the input data on collections...
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!