Conditional string concatenation/building in JSF - jsf

I'm trying to convert a JSP Page to JSF (no JSP code allowed), but have stumbled upon an issue.
Note: This is academic, so no "dirty" solution will do.
I have jsp code that sets the image source and alt text of an image depending on various conditions. There are concatenations and switch conditions. This is inside a loop.
Now, I can reproduce the loop that goes through all the values, like this:
<ui:repeat value="#{gameapi.game.fieldsList}" var="field">
<h:graphicImage id="field#{field.fieldNr}" styleClass="field#{field.fieldNr}"
url="..." alt="" title=""/>
</ui:repeat>
However, there's a total of over 20 combinations for the image url and alt text. Obviously, I doubt writing a conditionally rendered or chosen graphicImage Tag for every possibility is an elegant solution, since this would only get uglier with every additional combination.
I also cannot create those strings in the underlying java code, since that would violate the idea of separating view, model and controller.
So what is the best solution to do this? It seems like a huge weakness of JSF.

Consider using a variation on the MVVM pattern. You can have managed beans that are dedicated to view logic separate from the business logic managed beans.
<ui:repeat value="#{bizBean.list}" var="_row">
<h:graphicImage
url="#{viewModelBean.images[_row.outcome]}"
alt="#{viewModelBean.alts[_row.outcome]}"
title="#{viewModelBean.titles[_row.outcome]}" />
</ui:repeat>
viewModelBean could be an application-scoped type with a bunch of map properties. This assumes a relatively simple case, but the pattern is suited to more sophisticated requirements.
Note: the repeating control should be a NamingContainer, so trying to set the client identifier in the VDL is redundant. See here for more.

Related

primefaces update attribute not working on modal dialog opened from modal dialog [duplicate]

I have a question about the idea behind the fact, that only UIForm got the attribute prependId. Why is the attribute not specified in the NamingContainer interface? You will now probably say that's because of backward compability but I would preferre breaking the compability and let users which implement that interface, also implement methods for the prependId thing.
The main problem from my perspective about the prependId in the UIForm component is, that it will break findComponent()
I would expect that if I use prependId, then the NamingContainer behaviour would change, not only related to rendering but also when wanting to search for components in the component tree.
Here a simple example:
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
Now when i want to get the panelGroup component I would expect to pass the string "group" to the method findComponent(), but it won't find anything, I have to use "test:group" instead.
The concrete problem with that is, when using ajax with prependId="false". The ajax tag expects in the attributes update and process, that the values care of naming containers. It's a bit strange that when I use prependId="false" that I have to specify the full id or path, but okay.
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
<h:form id="test1" prependId="false">
<h:commandButton value="go">
<f:ajax render="test:group"/>
</h:commandButton>
</h:form>
Well this code will render without problems but it won't update the panelGroup because it cannot find it. The PartialViewContext will contain only the id "group" as element of the renderIds. I don't know if this is expected, probably it is but I don't know the code. Now we come to the point where the method findComponent() can not find the component because the expression passed as parameter is "group" where the method would expect "test:group" to find the component.
One solution is to write your own findComponent() which is the way I chose to deal with this problem. In this method i handle a component which is a NamingContainer and has the property prependId set to false like a normal UIComponent. I will have to do that for every UIComponent which offers a prependId attribute and that is bad. Reflection will help to get around the static definition of types but it's still not a really clean solution.
The other way would be introducing the prependId attribute in the NamingContainer interface and change the behaviour of findComponent() to work like described above.
The last proposed solution would be changing the behaviour of the ajax tag to pass the whole id, but this would only solve the ajax issue and not the programmatic issues behind the findComponent() implementation.
What do you think about that and why the hell is it implemented like that? I can't be the first having this problem, but I wasn't able to find related topics?!
Indeed, UIComponent#findComponent() as done by <f:ajax render> fails when using <h:form prependId="false">. This problem is known and is a "Won't fix": JSF spec issue 573.
In my humble opinion, they should never have added the prependId attribute to the UIForm during the JSF 1.2 ages. It was merely done to keep j_security_check users happy who would like to use a JSF form with JSF input components for that (j_security_check requires exact input field names j_username and j_password which couldn't be modified by configuration). But they didn't exactly realize that during JSF 1.2 another improvement was introduced which enables you to just keep using <form> for that instead of sticking to <h:form>. And then CSS/jQuery purists start abusing prependId="false" to avoid escaping the separator character : in their poorly chosen CSS selectors.
Just don't use prependId="false", ever.
For j_security_check, just use <form> or the new Servlet 3.0 HttpServletRequest#login(). See also Performing user authentication in Java EE / JSF using j_security_check.
For CSS selectors, in case you absolutely need an ID selector (and thus not a more reusable class selector), simply wrap the component of interest in a plain HTML <div> or <span>.
See also:
How to select JSF components using jQuery?
How to use JSF generated HTML element ID with colon ":" in CSS selectors?
By default, JSF generates unusable ids, which are incompatible with css part of web standards

JSF: Custom component in tables not rendered as expected

Is there a suitable solution for the custom component root-issue in the meanwhile?
In short terms, the problem is that using custom components containing of both a label and an input field within a table like
<h:panelGrid columns="2">
<jl:inputField value="#{testBean.value1}"/>
<jl:inputField value="#{testBean.value2}"/>
</h:panelGrid>
... will be rendered within a single row.
A dirty solution would be to place the panelGrid within the component which will cause a rendering of a separate table for each input field. This is most likely the case cause there isn't a bottom-up but a top-down approach when parsing the code.
Do you have any other ideas how to handle this? Custom tags were mentioned in the discussion.

JSF best practices : One form for the whole application or a few smaller forrms?

What is the best practice in JSF , to create one main <h:form> in template for example and put all content inside or to have a few forms for each parts, for example if we have two logical blocks of code on the page we should have wrapped these blocks in 2 separate forms ???
This is an overly broad question, and it as well has nothing to di with JSF. It is a question of HTML understanding and design.
If you abstract away all of the JSF details, you'll find out that the rendered component is a plain HTML <form>. To recall the specification, a form is:
a section of a document containing normal content, markup, special elements called controls (checkboxes, radio buttons, menus, etc.), and labels on those controls. Users generally "complete" a form by modifying its controls (entering text, selecting menu items, etc.), before submitting the form to an agent for processing (e.g., to a Web server, to a mail server, etc.)
So ultimately a whole form will be submitted to the server. In case of a component-based framework, like JSF, the bound values of components will populate the backing beans with the submitted data, in case there are no errors.
But what data will be submitted? All data that is within a form. So, if you have one global form that means that all unrelated pieces of information will be collected: like user credentials, product choices, selection of preferences, etc. And it will be done all at once. Most probably it won't yield the desired functionality, but will produce unexpected results.
The problem there was mixing of concerns: one form contained non-related data that was not designed to be submitted together. This leaves us with a one-form-per-user-interaction, like one form for user authentication/logout, another form for storing user preferences, yet another one for keeping product choices, etc. One global form also is likely to leave you with nesting forms problem, taking you some time to figure it out.
Regarding the choice of where to put that form, it is as well depending on the logical separation: if you have user login/logout on every page it could be placed in master template. Per-view forms are likely to be put in template client. Moreover, you'll find it convenient to sometimes put them side-by-side to distinguish the functionality.
Also, form may alter the expected behaviour. One final example: user choice of products. Consider two cases.
The first one:
<h:form>
<ui:repeat value="#{bean.purchasedProducts}" var="product">
<h:outputText value=#{product.name}/>
<h:inputText value=#{product.quantity}/>
<h:commandButton value="Change"/>
</h:dataTable>
</h:form>
The second one:
<ui:repeat value="#{bean.purchasedProducts}" var="product">
<h:form>
<h:outputText value=#{product.name}/>
<h:inputText value=#{product.quantity}/>
<h:commandButton value="Change"/>
</h:form>
</h:dataTable>
While the first example will update all products, the second one will update only the relevant product.
Finally, there is no 'best practice' or 'universal solution'. I think that it's best to depart from separation of concerns when designing an HTML document.
And, yes, I'm voting to close the question.

Seam conditional render without parsing

I'm trying to make a conditional render in my Seam application (2.2.0), to display two different controls depending on a condition.
I'm using the s:fragment tag with the render attribute, but my problem is that I want whatever the control is displayed, to have the same id:
<s:fragment render="${editable}">
<rich:calendar id="entityDate"..../>
</s:fragment>
<s:fragment render="${!editable}">
<h:outputText id="entityDate".../>
</s:fragment>
My problem is that even when the render attribute set to false, the "not to be rendered" element is parsed, and I get an exception because of the duplicated id.
I also tried with the tag <ui:remove>, which effectively removes the element before the parsing phase, so I can have something like:
<span id="myId"/>
<ui:remove>
<span id="myId"/>
</ui:remove>
Unfortunately the <ui:remove> tag doesn't allow conditional logic. Has anyone found a way to solve this?
That's only possible when you use a view build time tag such as JSTL <c:if>.
<c:if test="#{editable}">
<rich:calendar id="entityDate" />
</c:if>
<c:if test="#{!editable}">
<h:outputText id="entityDate" />
</c:if>
(note that this is not going to work within an iterablte JSF component, such as <ui:repeat>, <h:dataTable> and so on)
After all, I strongly recommend to take benefit of the disabled attribute instead, if necessary with a good shot of CSS to hide the input field borders and so on. It'll minimize the JSF view boilerplate code.
<rich:calendar id="entityDate" disabled="#{!editable}" />
Disabled inputs are separately styleable by the CSS attribute selector element[attribute], e.g.
input[disabled] {
border: 0;
}
The above removes the border of input elements with the disabled attribute present so that it look like a normal output text.
"Solve"? There is nothing to solve here: two elements in a GUI can not have the same ID. Hardly unnatural or unsound?
It's like asking: "I have a database table with two rows, I would like them both to have the same primary key value, but somehow I get these errors... has anyone managed to solve the problem and circumvent the constraints?".
Or even closer analogy: "I have two spans, one of them is invisible (has style="display: none") I would like them both to have the same id - and browsers seem not to like it, despite one of the spans being invisible".
Bottom line: rendered on not rendered, each component is still a part of the view tree, and therefore has a UNIQUE id.
I have a suspicion that you want to have some "polymorphic" code that should work with the currently visible element. Using ID for such code IS WRONG. If you show us your use case, we might find a right way to achieve the effect.
I use selenuim myself in a seam environement and i recommend using defined ids whenever possible. First you have the ability to create smaller ids which is usefull for pagesize. Second the selenium test run alot faster if you use ids for referencing instead of other selectors. I have not yet found a selenium test where you cannot handle diffrent ids. Additionally if a code fails in jsf tree creation you see which id is failing.
I see you are using sfragment with editable or not. I use the sdecorate and give the decorate an id and then "just" ed for the input and vi for the outputtext for example. This makes it easy in selenium to check the availability of edit or view components.
Would you be able to get the same results you need by putting the id tag on the fragment?
So:
<s:fragment id="entityDate">
<rich:calendar render="${editable}" />
<h:outputText render="${!editable}" />
</s:fragment>

Is it suggested to use h:outputText for everything?

I'm new to JSF (just started learning about it 4 days ago) and I'm a bit confused about the usage of h:outputText. I know that is a simple tag, but in most examples I've seen, it's used to output very simple (no need to escape), non-i18n text. For example (taken from here)
<h:outputText value="Transport" />
which could be replaced by
Transport
So, I'm wondering if I'm missing something or if most of the examples I've seen are overcomplicated to the point of insanity.
If you're using JSF 2.x with Facelets 2.x instead of JSP, then both are equally valid. Even more, Facelets implicitly wraps inline content in a component as represented by <h:outputText> (in other words, it will be escaped!).
Only whenever you'd like to disable escaping using escape="false", or would like to assign id, style, onclick, etc programmatically, or would like to use a converter (either explicit via converter or implicit via forClass), then you need <h:outputText>.
I myself don't use <h:outputText> whenever it is not necessary. Without it, the source code becomes better readable. You can just inline EL in template text like so #{bean.text} instead of doing <h:outputText value="#{bean.text}">. Before JSF 2.0, in JSP and Facelets 1.x, this was not possible and thus the <h:outputText> is mandatory. If your IDE gives warnings on this, it's most likely JSF 1.x configured/minded.
The example you quote is written in XHTML - which is XML. A standalone 'Transport' may not be allowed at the position you want to put it in, so that you need to "transform" it into valid xml.
IIrc this what is called facelets and the default in JSF2, while in JSF1, the presentation code could be done with JSP tags as default and facelets was an alternative that many developers were using).
h:outputText tag is required only if you are rendering the text based on some render condition.
eg: <h:outputText value="Transport" rendered="#{myBean.displayText}"/>.
If its a simple output statement then there is no need of using the tag; you could just use: Transport

Resources