I've found some tutorials on the web regarding building custom components. However, I can't seem to figure out if the tag-lib is required or not as of JSF 2.2, which is part of JEE7 and what I am coding to. I thought I just put the xhtml file in the /resources/components folder, the bean and component classes are part of the project, and then I include the jsf/composite/<path> in the xhtml pages I wish to use the component with... so are tag-libs also required, or are there specific scenarios where you must have them, or are they optional?
The first way - which I recommend - is to simply code up the custom component using the JSF Facelets tags provided for that purpose.
The second way is to create a custom binary component. This is more powerful, but much more expensive.
JSF binary components started out as taglibs on steroids, but as JSF has evolved, the binary component code has become more and more foreign to that architecture. For starters, traditional taglibs rendered servlet code directly. JSF doesn't convert to servlets. It converts to a Component Tree data structure, which can be rendered as HTML, but can also be rendered by other types of renderers, such as a PDF renderer, a WAP renderer, an HTML5 renderer, and so forth. The renderers are plug-in components in their own right, so the rendering code is contained in the tag library, but isn't intimately intertwined with the tag's internals. Because to do so would negate its plug-replaceable properties.
Then there's the whole bit about tag attributes. In original JSPs, tag attributes were directly reflected as taglib POJO bean properties. In JSF, they aren't. Plus, there's the whole mess involving EL evaluators, which have gone through some non-trivial changes over the course of the JSF architecture's lifespan.
So, in short, while there are times when a binary component is the only way to go, you should think long and hard. First you'll have to "treasure-hunt" for the right versions of the documentation needed to design and implement the tags. Then you'll have to actually create it, allowing for the fact that the number of people who can help you is far smaller than it is for vanilla JSF. And finally, you'll pay repeatedly when new versions of JSF come out to adapt the bean to allow for changes to JSF's internal structure and architecture. At least until JSF comes up with something so clean and simple that it no longer mutates that way.
But a more direct answer to your question: I don't think that the 2.x versions of JSF require TLDs for custom binary tags. However there is an XML file that defines custom tags that's new for JSF2.
john lazeraski wrote:Tim, you are always helpful with your replies. Thank you.
So I'll stick to the non tag-lib form and try to figure out how to make that work with bits of ajax and server side dependent bean code.
You'll sleep better at night.
Don't forget that if you're using an extension taglibrary such as RIchFaces or PrimeFaces, that jQuery is a part of what makes them work internally, so you too can tap into jQuery without incurring any extra cost. Although it might be a fairly old copy of jQuery in some cases.
Couple questions if you can explain them.. I have some idea but still a little misunderstood with regards to components. I want what I consider a simple component. As in many forms, there are address, email and phone fields to enter. I don't like the idea of displaying 2+ of each set of fields taking up valuable screen space "just in case". Instead, I want a + button that dynamically adds a set of fields if the user needs. Each set would have a - button to remove them as well. Oddly I can't seem to find much info on how to create such a component in JSF, and I would have thought PrimeFaces or something would already have a component like this, or something similar. Maybe it does and I am missing it. At any rate, naturally I want to avoid a page refresh every time a + button is pressed. So using some ajax when the + or - button is pressed, it needs to update the model from what I've read on the server side, then use the render="" to re-render the same div element but with the updated model to include the new set of fields.
What I am not sure of is if I need two separate classes for this.. one for the model, and one to handle the form submit (pojo bean). I've seen some code around that uses a listener to handle the ajax request when the button is pressed, but still not quite clear on how this all fits together. I think it uses the ajax request lifecycle to update the model (adding new fields in), then the response some how pulls the updated render output to refresh the page in-line?
My experience in the past with ajax was pretty straight forward.. using jquery or prototype, make a request in a js function, the response html was then innerHtml'd to update the web display with the returned html. I assume the render="element id" handles the response, but not sure how the code on the server side return a chunk of newly added (or removed in the case of the - button pressed) html.
Anyway, I'll keep stabbing at it, if you can elaborate (as you do so well) on any of this, I'd appreciate it.
If the control set is homogeneous, simply map the model control set as a row in a dataTable, and every time you want a new row of controls, create a new model row for that control set, add it to the dataTable's TableModel object, and re-render the table.
If the control set is heterogeneous, you have one of the rare valid excuses to tap into JSF internals. Select a naming container to frame them (a panelGrid is often good), bind it to a Component property in the backing bean, and every time you want to add a row of controls, dynamically construct them, add them to the component's children list, and re-render the container.
One of the extension tagsets also offers a third option: an extension tag specifically designed to take model layouts and render from them. It's either PrimeFaces or IceFaces, I think.
I saw some code that added actual controls in the server side bean, I assume that was similar to your 2nd example.
It seems odd to me to use a daa table to render fields inside a data table component with custom layout.. is that normal in JSF? I mean, when I think of a data table, I always think of a tabular table layout with columns and rows. In my case, I would want each component to have a specific layout.. for example the address component would not have every field across a table, but instead the address 1,2,3 lines would be vertical, with the city/state/zip side by side on another row, etc. So when you say to use a table model and data table.. do you mean I can layout the resultant set of fields however I want and to use the component for it's ability to loop through the model? Or when you use a data table (in JSF) it always results in a column/row like table that is typical of a database GUI admin tool?
A ui:repeat tag could be used if you wanted something less structured towards vertical rows with columns. For example, a horizontal layout of similar controls.
Some of the extension taglibraries support things like subtables. That can help with things like this:
Each of the 2 sub-tables would have a sub-model, which in this case would contain the label and value objects.
john lazeraski wrote: Ok.. but I thought ui:repeat was sort of like using JSP and scriplets.. not recommended in JSF 2?
john lazeraski wrote:For that matter, using jstl and such is also frowned upon is it not? Or at the end of the day does it not matter?
JSP and scriptlets = BAD in JSF2 (scriptlets are frowned on even without JSF any more). JSP is deprecated in favor of xhtml (View Template Language) and scriptlets might not even run at all, since a View definition doesn't compile down into a servlet the way that a JSP page does. It's distilled into the Component Tree, which is a data structure.
ui:repeat, like all of the ui tagset are Facelets. Facelets actually wasn't even a standard part of JSF until JSF2, although it was easy to add on as an extension to JSF1. I don't recommend it because for basic 2-dimensional layouts, the core tagset is capable, and "repeat" is something that people think gives them and excuse to put code on the View. Actually "repeat" should be read more like "repeated elements", not "repeat-while". The main use for ui:repeat is when you do need to repeat a set of elements in a way that's not compatible with the dataTable paradigm. For example, a set of controls that run horizonally instead of vertically (where each control could occupy a row in a table).
Oracle docs say that JSF2 supports JSTL. Believe them and you'll discover the truth painfully. JSF2 is a lot more co-operative with JSTL than JSF1 was, but it still has knives waiting for the unwary. Plus there's the old "code on the template" issue, since the more commonly-used JSTL constructs are logical (if/then, loop, etc.). And as I've said many times, logic in the View template is not only a violation of MVC's Separation of Concerns, it's expensive to maintain.
Besides, all of the basic JSTL functions have equivalent (and cleaner) JSF functions.
The main use for ui:repeat is when you do need to repeat a set of elements in a way that's not compatible with the dataTable paradigm. For example, a set of controls that run horizonally instead of vertically (where each control could occupy a row in a table).
Forgive me Tim as I am still a little foggy on what the dataTable paradigm encompasses and how it works.. I do need to learn it but have not yet used it.. in my example above where I have the address fields as a composite component with a + button to dynamically add them at runtime, they layout might be something like:
Addresses (Press + to add another address or - to delete an existing address) <add>
Address Type: [drop down with home, work, vacation, other] <del>
Address Line 1:
Address Line 2:
Address Line 3:
City: State: Postal Code:
Address Type: [drop down like above] <del>
Address Line 1:
Address Line 2:
Address Line 3:
City: State: Postal Code:
Then emails and phone numbers are easier than the above.
To me this is NOT a data tabular layout to display these components. I want a - (or image, etc) for each to delete, at some visible location, then as you see from above, the label and the input field. In the case of city/state/zip, they'd be on the same line, although they certainly don't have to be. Anyway, I just want to be clear, from what you are saying, it sounds like I *would* use a ui:repeat in this case because it isn't suited for a data table layout. Same with the emails and phone numbers. One thing to keep in mind (at least to me) is that because the address, email and phone components are similar in that they use a + to add a new one, a - to delete existing one, keeping them within the same sort of container and how they are rendered seems the right choice here. In other words, if the address component with it's layout may fit the ui:repeat model, but the other two being single lines (label + input) might fit a data table model.. I'd argue that using the same ui:repeat for all three would make more sense, especially in terms of maintainability, but also the ease of copy/paste of the code with changes.
In the case of the ui:repeat, since I wouldn't have a datamodel behind the scenes, then I would need a custom listener method in a bean that then adds the newly constructed components (on the server side) as children of the framing container, correct? In that case, does the f:ajax render="container div id" take care of re-rendering the container with the newly added components (or removed in the case of a - press)? I believe that is how it would work.
You can also use a datatable in cases where you have things like table-in-table. In your particular case, possibly ui:repeats within an h:datatable. Although you may not need the outer model, in which case, an alternative would be an h:panelGrid.
Yet another possibility would be to discard the whole idea of repeating anything. Lay out a panelGrid, make its cells be panelGroups, each containing the elements you want, and use the "rendered=" attributes to show/hide the panelGroups, thus displaying/hiding the collections of sub-elements.