This week's book giveaway is in the JavaScript forum.
We're giving away four copies of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js and have Paul Jensen on-line!
See this thread for details.
Win a copy of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js this week in the JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Composite component or ui:repeat with List  RSS feed

 
john lazeraski
Ranch Hand
Posts: 77
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am trying to figure out what is best for my specific use. Users of my site will need the option to add multiple emails, addresses and phone numbers not only for their profile, but in a couple other areas of my site where users have clients, and each client can have multiple emails, phones, and addresses. I thought a component might be best for reuse, but I am having a difficult time being new to JSF2 figuring how to provide dynamic javascript field additions for a composite component. Using the ui:repeat and a pojo bean with a List or Collection allows me to loop through each of the types of objects, and controlling the markup. But I don't want to repeat the code on other pages where the same sort of input is needed. On the other hand, a users profile backing bean and submit handling code is different than when a user adds multiple emails/addresses/phones to a client.. different code to store it, etc.

So basically I need something like a component that can be used multiple times on the same page (for example a page with emails, addresses and phone numbers on it would use the component 3 times). It needs to be able to have a + button that dynamically adds another set of fields when clicked, and each set of fields has a - button to delete it, which in turns deletes it from the server side as well. The whole set of fields (1 or more emails for example) should be in a collapsible panel to show/hide as needed so as not to pollute the vertical space.

Anyone done anything like this and has an example of code or can provide a little insight as to the best way to approach this?

Thank you.
 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My usual rule is to use the "h:-space" controls where possible and leave the "ui:-space" controls for functions that they cannot handle. For example, the h:dataTable is my preferred mechanism for containing 2-dimensional row/column tabular display elements (as opposed to ui:repeat), and ui:include or component elements for recyclable complex control definitions. The h:dataTable has the advantage that its associated DataModel makes it easy for action code to determine what row of a table you are working with.

Most of my major apps at the moment are enhanced with JBoss RichFaces, which include an collapsable container control element (although CSS can be used to do this on a "brute force" basis).

To use JSF effectively, you shouldn't be thinking in terms of logic (i.e., "looping") in your View definitions. Views are 2-dimensional layout specifications. Life will be a lot more pleasant if you treat them as such, and leave the logic for the Models (backing beans) and the JSF (pre-written) Controllers.
 
john lazeraski
Ranch Hand
Posts: 77
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Couldn't agree more Tim. I don't use the jstl stuff either if possible.

I gather what you're saying is, find a way to use a component with the h: and p: (primefaces is what I use), add javascript to handle the ajax reuqest to dynamically add new elements into the DOM.

The question then for me is, what is the right way to give each form element that is added by javascript, names.. so when a form is submitted.. it can be processed. Right now, when I use a single form with some fields, I have a pojo bean with @Named() (using Glassfish 4 and JEE7), and that gets populated and my method in that same bean that the button calls can access the form submitted data. However, if I dynamically add new fields with javascript, I can't insert #{beanName.fieldName}.. I need to provide an actual name for the field. The two ways I used to do this was either set up a collection on the setter (back in the day of JSP pages.. ugh) with the same name. The other way was to loop through the fields (for example, if I had 5 email fields) with something like name="email_1", "email_2", etc. Then in the method I grabbed the request object and looked for all "email_*" names and handled it that way.

So with JSF2, backing bean with a collection of object type, with javascript adding dynamic fields at runtime, what is the right way to provide names for the fields, and then how to handle the form submit process with the newly added fields?

In my case, as I described above, I have one or more emails, one or more addresses and one or more phone number fields. This could apply to any custom set of fields though, so the way to handle it should be the same regardless of the type of group of fields.

Thanks.
 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you attempt to use JavaScript to add elements into the DOM in JSF, you WILL regret it. Search our forum and learn from the pain of those who have gone before!

You're far better expanding the DOM by expanding the Model. For example, adding rows to a DataModel instead of trying to add rows to a table view via JavaScript.

Where you can, allow for all displayable elements and use "rendered" attribute to show/hide them. Only if you absolutely, positively cannot get what you want by manipulating the Model by itself should you use the "binding" attribute to give the Model direct access to the Component Tree and dynamically alter it. Of all the apps I currently support, only one of them required that. And I have wondered in retrospect about that one.

If you use the Facelets ui:component facility to construct a complex control, you can "parameterize" it, thereby propagating unique IDs into its internal sub-controls. This is different from what I discourage (parameterizing calls to the model) in that basically, the ui:component is a macro, not a function.

I've said before that you shouldn't "program" a View, you should specify it (declarative coding). Related to that is that you shouldn't get bogged down in the internals of HTML forms handling. In JSF, the form delimits the set of controls whose values will be transferred to the model by their respective sub-Controllers when a command is fired and the fact that it's (usually) done via HTML FORM submit is merely incidental.
 
john lazeraski
Ranch Hand
Posts: 77
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey Tim.. thank you again, you're quite the expert! I like this way of thinking. This truly reminds me of Swing coding years ago where we updated the model, then invalidated the view to repaint the screen with the updated model.

One question comes to mind.. if I update the model (on the server), can I see the additions added to the web page UI without a full page refresh? I am sure you know the sort of UI I am talking about.. I want a smooth UI where only a portion of the UI changes, either showing or hiding elements including adding or removing them, without a full page refresh. I am pretty sure that JSF 2 can handle this, although from my reading, it seems the primary way this is done is with the <f:ajax> tag and if I recall correctly a target element ID to replace. In my case, if I have an outer h:panel with id "outer" and want to add a set of elements when a + button is clicked, would I basically "invalidate" the entire outer element (panel) so that it repaints just that panel from the updated model?

 
Tim Holloway
Bartender
Posts: 18662
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're on the right track.

A normal command (button or link) submit does a full-page refresh. AJAX was specifically invented for 2 things: partial forms submit and partial page refresh. And the "render" attribute on an AJAX tag does in fact, signal what parts of the view have been "invalidated".
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!