How to use ui:include inside a forEach and use the loop variable inside the included page? - jsf

I'm upgrading to JSF 2.0.2 inside Tomcat 7.0.12 and I have a page with a variable number of reusable widgets on it. I used to use t:aliasBean for this purpose, but it doesn't seem to work. I'm now trying the following in my Xhtml:
<c:forEach items="${viewBean.currentView.parts}" var="part">
<t:div styleClass="div#{viewBean.partNumber[part]}">
<c:forEach items="${part.widgets}" var="widget">
<f:subview id="div#{viewBean.widgetId[widget]}">
<ui:include src="widgets/#{widget.widgetPage}">
<ui:param name="widget" value="#{widget}" />
</ui:include>
</f:subview>
</c:forEach>
</t:div>
</c:forEach>
What seems to happen is the next widget from the loop is used in the previous widget's page, so I get errors unless there is only one widget.
Edit: I've tried ui:repeat - it doesn't work. I've also tried removing the ui:include, just as a sanity test; the looping works fine. Also, I'm using Spring 2.5.6.SEC01 - though it shouldn't matter.

I propose to use ui:repeat instead of c:forEach.
Why?
The most important thing to understand
about the jstl tags in Facelets is
that they do not represent components
and never become a part of the
component tree once the view has been
built. Rather, they are tags which are
actually responsible for building the
tree in the first place. Once they
have done their job they expire, are
no more, cease to be, etc etc.
Source [here][1]. I really recommend to read the entire article.
UPDATE:
Please note that I do not say that c:forEach is bad. I want to underline that mixing it with ui:repeat it's not recommended.
[1]: https://rogerkeays.com/jsf-c-foreach-vs-ui-repeat

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

how to generate dynamic rich:panelMenu?

i have a problem to generate dynamic menu, i'm using JSF1.2. I tried the c:forEach with an arrayList to generate dynamic rich:panelMenu as BalusC advised in a related forum, but get Accessor never triggered in c:forEach. it ruined me a day. can anyone provide me a solution ?
<c:forEach items="#{serviceListBean.services}" var="child">
<rich:panelMenuItem mode="none">
<h:outputText value="#{child.serviceId}"></h:outputText>
</rich:panelMenuItem>
</c:forEach>
what's wrong in this code? can anyone enlighten me?. For info, serviceListBean is request scoped bean.
Two possible causes:
JSTL is not declared as taglib in JSP or Facelets. To confirm this, rightclick page in browser and choose View Source. Do you see <c:forEach> tag unparsed among the generated HTML? If you're using JSP, declare it as follows:
<%#taglib prefic="c" uri="http://java.sun.com/jsp/jstl/core" %>
Or if you're using Facelets, declare it as follows in root element:
xmlns:c="http://java.sun.com/jsp/jstl/core"
On some servers like Tomcat, which doesn't ship with JSTL out the box, you would also need to install JSTL first, see also this info page.
This piece of code is in turn been placed inside a JSF repeating component, like <h:dataTable> with a var="serviceListBean". This is also not going to work. You would need to replace the JSF repeating component by <c:forEach> as well.

How to set value in bean using use c:set with jsf?

I have another problem to solve. I have a code on my xhtml page:
<t:dataList id="myDataList" value="#{myBean.myList}" var="element" first="0" `rows="10" dir="LTR" frame="hsides" rules="all">`
<c:set target="#{myBean}" property="fid" value="#{element[0]}"/>
...
</t:dataList>
The problem is that value of 'fid' in a bean is null when I`m checking it. When I wrote:
<c:set target="#{myBean}" property="fid" value="8"/>
everything works fine and value is set to '8'. How should i fix this? Thanks for replies.
JSTL tags runs during view build time. JSF tags runs during view render time. You can visualize it as follows: JSTL runs from top to bottom first when the JSF component tree is to be populated, then hands over the component tree to JSF and finally JSF runs from top to bottom to render the HTML.
The element[0] is not there when JSTL is creating the view. It's only there when JSF is rendering the HTML. However, 8 is hardcoded and it is always there.
There are several ways to achieve it the proper way, but since the functional requirement is unclear, I can't suggest a proper approach. Maybe you need f:setPropetyActionListener. Maybe you need DataModel#getRowData() or UIData#getRowData(). Or maybe you don't need it at all.

Why prependId="false" in a jsf form?

I know what prependId="false" does. It set the flag so that the id of the form does not prepend the id of the form child, but why? any particular reason why you do or dont want to prepend id?
In my experience, I never use this attribute. However, in some cases it can be useful.
When you use Facelets, you can create templates or include pages inside another page. So you can imagine that a page could be included in several different pages. Take the example where the parent pages contain a form, with different id:
Page 1:
<h:form id="form1">
<ui:include src="pages/my-page.xhtml"/>
...
</h:form>
Page 2:
<h:form id="form2">
<ui:include src="pages/my-page.xhtml"/>
...
</h:form>
Now, in the my-page.xhtml, you have a <h:inputText id="foo"/>. In the first case, the real ID of the input will be form1:foo, while in the second case, it will be form2:foo. This could create complex situations if you need a direct access to this component in Javascript or in Java (using findComponent("...") method).
If you use prependId="false" (or on some components forceId="true"), the real ID will be simply foo, and then your code will be simpler as you will not have to care about the container of the input field.
However, you will have to use this attribute carefully, as you may get a duplicate ID error if you use this prepend attribute too often...
In modern jsf versions it might also break ajax, see UIForm with prependId="false" breaks <f:ajax render>
A situation where prependId=false is useful is in the login form, if you are using Spring Security, because the ids of the inputtexts have to be exactly "j_username" and "j_password". So you shouldn't put the form id before them, and using prependId=false is a good choice to acheive this.
I prefer to add prependId occasionally to make styling elements via their ID classes easier. For example, a form:
<h:form id="myform" ... >
<h:inputText id="mytext" ... />
</h:form>
Would give you an ID of myform:mytext. As the colon is reserved in CSS, you have to escape the CSS to read something like #myform\:mytext { ... } which I prefer not to do. With prependId="false" I get to use just #mytext { ... } which is much simpler & nicer to read. It also plays nicer with CSS preprocessors like LESS or Sass.
One scenario where we have to set this flag is in case of Autocomplete control of primefaces library.
I had to set this flag to false when I was trying AutoComplete control of primefaces library. I was not able to get autocomplete working but after setting this flag it worked fine. You can see this link to my question regarding this problem
WARN [Parameters] Parameters: Invalid chunk ignored. warning coming in primefaces application
In addition to making for CSS selectors easier, using prependId=false makes it easier to use JavaScript and jQuery to access specific elements.
Otherwise, without using RichFaces, to get at an elmement by id using jQuery you'll have to use an ugly escape sequence like:
jQuery("form-id\\:element-id")

JSF <h:outputFormat>: use array values as parameters

On my JSF2 page, i'm using internationalized error messages.
In my backing bean, i'm putting the messages into the flash Scope:
flash.put("error", exception.getType());
On the page, this string gets translated this way:
<h:outputText value="#{bundle[flash.error]}"/>
Works fine.
NOW i want to be also able to put (an arbitrary number of) parameters into the message text, that get inserted into the placeholders in the i18n-property in my message.properties. Therefore, i'm putting the parameters as a String array into the Flash Scope, like this:
//exception.getParameters returns String[]
flash.put("errorParams", exception.getParameters())
Now i also want to be able to use this String array as parameters for an outputFormat element, to insert them into a property like Welcome, {0} {1}.
So i tried to achieve this by using ui:repeat:
<h:outputFormat value="#{bundle[flash.error]}" rendered="#{! empty flash.error}" class="invalid">
<ui:repeat value="#{flash.errorParams}" var="_param">
<f:param value="#{bundle[_param]}"/>
<!-- also doesn't work: <f:param value="#{_param}"/>-->
</ui:repeat>
</h:outputFormat>
Unfortunately, the param value is ignored and the placeholders of the i18n-property aren't replaced, so the rendered output is Welcome, {0} {1}. When using a "regular" repeater, displaying the array elements just as an outputtext, it works. So the outputFormat tag doesn't seem to support the use of a repeat as a child.
Damn, so close ;) Anyone knows a good way to do what i want, or is there any component library supporting something like that?
The problem here is that ui:repeat is a render-time child of h:outputFormat which it indeed doesn't support at all. You'd like to put multiple f:param elements directly as children of h:outputFormat during build time.
The c:forEach is suitable for this task. The JSTL core tags (which are already included in Facelets, so you don't need to install any extra JARs) do their job during building the view tree, right before it's JSF turn to process/render the view tree.
<html xmlns:c="http://java.sun.com/jsp/jstl/core">
...
<h:outputFormat value="#{bundle[flash.error]}" rendered="#{! empty flash.error}" class="invalid">
<c:forEach items="#{flash.errorParams}" var="_param">
<f:param value="#{bundle[_param]}"/>
</c:forEach>
</h:outputFormat>

Resources