0 and i need to render some buttons based on condition, i'm getting the condition true but each time i visit the page the button its displaying with additionl buttons,here's my code
<ui:repeat var="r" value="#{sessionScope['restrictpageload']}" varStatus="status">
<ui:repeat var="permission" value="#{restrictPageLoad.isUserHasFeaturePermission(4,'abc')}" varStatus="status2">
<ui:fragment rendered="#{permission.featureCreate eq 'y'}" >
<h:commandButton value="Button1" action="#{bean.method()}"/>
</ui:fragment>
</ui:repeat>
</ui:repeat>
here my first <ui:repeat> gets the values from session and i'll pass as parameter to second and this will return me arraylist and i'm going to render the button based on condition.
I'm getting the values inside but each time i visit page two more button addsup.Please help.
too long for a comment...
3 points:
outer loop declares r and status which are not used in inner loop, so "here my first <ui:repeat> gets the values from session and i'll pass as parameter to second" is false
value="#{sessionScope['restrictpageload']}" is equivalent to value="#{restrictpageload}"
value="#{sessionScope['restrictpageload']}" maybe there's a typo. you mean value="#{sessionScope['restrictPageload']}" (uppercase P)
maybe you want to do something like this:
<ui:repeat var="restriction" value="#{bean.pageRestrictions}">
<ui:repeat var="permission" value="#{bean.userPermissions}">
<ui:fragment rendered="#{restriction == permission}">
<h:commandButton value="Button1" action="#{bean.method}"/>
</ui:fragment>
</ui:repeat>
</ui:repeat>
or better
<ui:repeat var="restriction" value="#{bean.pageRestrictions}">
<ui:fragment rendered="#{bean.userHasFeaturePermission(restriction)}">
<h:commandButton value="Button1" action="#{bean.method}"/>
</ui:fragment>
</ui:repeat>
however if your buttons are duplicating, you are adding something to your loops, maybe in isUserHasFeaturePermission?
UPDATE (comment reply)
read carefully the accepted answer of your linked question:
Your question is meaningless. There is no "passing parameters by " and there is no "passing parameters using ". Your words might make sense in some specific context - but the context is missing.
not related but worth mention, NEVER use c:forEach in JSF pages, unless you know exactly how JSF lifecycle works.
passing parameters in expressions depends on EL (ExpressionLanguage) library version.
you can pass parameters only if you have EL 2.2+. this library is shipped (normally) with the servlet container.
read this answer and linked for a complete explanation.
what's your servlet container? tomcat 6.0, glassfish 3.1?
however, does it throws an Exception?
Related
In JSF2 I have an XHTML like this:
<h:form id="myForm">
...
<c:forEach items="#{myController.header}" var="hd" varStatus="count">
#{hd}
<h:selectOneMenu value="#{myController.type[count.index]}" id="formtype" >
<f:selectItem itemValue="Nop" itemLabel="Nop" />
<f:selectItem itemValue="Yep" itemLabel="Yep" />
<f:ajax render="#form" />
</h:selectOneMenu>
#{myController.type[count.index]}
<h:selectBooleanCheckbox value="#myController.valid[count.index]}" id="valid">
<f:ajax render="#form"/>
</h:selectBooleanCheckbox>
#{myController.valid[count.index]}
</c:forEach>
...
</h:form>
And my managed bean has:
private String[] type;
private boolean[] valid;
which I initialise (type = new String[...]; and assign a value to each position) when the named bean is 1st loaded.
If I modify the combo or the check box, it works, the value is changed in the managed bean and the new value gets printed (rendered) in the JSF page. But only the 1st time. Next changes do not modify anything at all. It is strange because I have similar code in other apps and works fine, so I am doing something incorrectly but cannot find it. My template has a h:header and I cannot see any logs in the JS console or in TomEE (I only see .INFO - The start() method was called on component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/myApp]] after start() had already been called. The second call will be ignored but I think it is unrelated). I have tried to add execute="#this"/execute="#form" and others unsuccessfully, and check all points of this post but nothing seems to apply to me.
What is the mistake I am not seeing?
EDIT
#Named(value = "myController")
#ViewScoped
public class MyController implements Serializable {
...
I also have a <h:messages globalOnly="true" showDetail="true" showSummary="true" /> in my template.
I think I got it, finally!
Thanks to two things:
Point 3 in BalusC answer. I added an id to my message in the template <h:messages id="msg" and then use <f:ajax render="#form msg"..... This made an error j_idt1: Validation Error: Value is required to appear.
Then I could find the solution in this post: to change the required parameter from true to <f:viewParam required="#{!facesContext.postback}". This was not required in my other apps because required was "false", since it could be called with parameter or without it. When it was called with a parameter, it worked because by serendipity the page could be called without it.
Ran into the exact same problem, my <f:ajax> tag would work the first time and then nothing... no error or anything on the page. After a few hours and countless googling nothing was turning up. (Most of the questions on StackOverflow were actually having the opposite problem, the Ajax wouldn't fire the first time but then it would work fine). I finally stumbled on this question which described exactly what I was seeing.
I was previously trying to re-render only a section of the page, but I noticed that once I changed the render attribute to "#all", I got the same error message describe above:
j_idt1: Validation Error: Value is required
I scrolled up and noticed I had a <f:viewParam> with required set to "true". I made the change described by user1156544 and that did the trick.
can I pass expressions to JSF 2 passthrough-attributes?
the following code is not working. expression #{country.isoCode} is not evaluated.
<h:selectOneMenu value="#{bean.selectedCountry}" styleClass="selectlist">
<f:selectItems
value="#{bean.countries}" var="country"
itemLabel="#{country.countryName}"
pt:data-icon="flag flag-#{country.isoCode}"/>
</h:selectOneMenu>
I am using namespace
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
and bootstrap-select. attribute "data-icon" is used to show an image. see:
http://silviomoreto.github.io/bootstrap-select/#data-icon
rendered output:
<i class="glyphicon flag flag-"></i>
EL is basically supported/evaluated over all place in a Facelet template. Also outside tags/attributes. Even in HTML comments, where many starters then fall over. So that's not the problem.
Your particular case is, unfortunately, "by design". Before rendering the first <option> element, the <f:selectItems> is is wholly parsed only once and turned into an iterator during which all EL expressions will be evaluated. Then, the component will iterate over it while rendering <option> elements during which all passthrough attributes will be evaluated. However, as the var was already evaluated during creating the iterator, it isn't available anywhere during rendering the passthrough attributes and ultimately evaluates to an empty string.
Fixing that would require quite some changes in standard JSF implementation of <f:selectItems>. I'm not sure if JSF guys would be all ears for that, but you can always try to create an issue.
You can work around this by creating physically multiple <f:selectItem> instances during view build time, with help of <c:forEach>.
<h:selectOneMenu ...>
<c:forEach items="#{bean.countries}" var="country">
<f:selectItem
itemValue="#{country}"
itemLabel="#{country.countryName}"
pt:data-icon="flag flag-#{country.isoCode}" />
</c:forEach>
</h:selectOneMenu>
See also:
JSTL in JSF2 Facelets... makes sense?
This example is from a book on JSF. The excercise is to refactor the following Facelets code while eliminating <c:if> and fn:toUpperCase(). Usage of <c:forEach> is allowed.
#{myBean.numbers} returns String["one","two","three"]
As the book is on JSF and not on Java, I suppose the existing Java-code is not to be touched. But I can't think of another way to do this solely in Facelets.
<c:forEach var="item" items="#{myBean.numbers}">
<c:if test="#{not fn:endsWith(item,'o')}">
#{item}
</c:if>
<c:if test="#{fn:endsWith(item,'o')}">
#{fn:toUpperCase(item)}
</c:if>
</c:forEach>
Only thing I can think of is using a converter that conditionally uses String#toUpperCase() and then I still do not understand why use of <c:forEach> should still be allowed:
<ui:repeat var="item" value="#{myBean.numbers}">
<h:outputText value="#{item}" converter="conditionalConverter"/>
</ui:repeat>
Is there a more "Facelets way" to do this (and still a need to use <c:forEach>)?
UPDATE:
Instead of <c:if> one could still use e.g. <h:outputPanel> and it's rendered-attribute, but there is still no Java-less replacement for fn:toUpperCase().
I am asking for learning purposes only. I suppose the <ui:repeat>-solution with a converter is the cleanest and represents most how JSF is supposed to be used. Do you think so, too?
As to <c:if>, the JSF alternative to JSTL <c:if> is the rendered attribute on any component. For example, <h:panelGroup> or <h:outputText>. Those components doesn't generate additional markup if there are no attribtues specified which should end up in HTML, like id or styleClass, otherwise they generate a <span>.
Here's an example of both:
<h:panelGroup rendered="#{not fn:endsWith(item,'o')}">
#{item}
</h:panelGroup>
<h:outputText value="#{fn:toUpperCase(item)}" rendered="#{fn:endsWith(item,'o')}" />
As to fn:toUpperCase(), JSF has no alternative. I'm not sure why you would need a JSF alternative as it's essentially not a tag, but a simple EL function which is perfectly usable in both JSTL and JSF tags. In any case, you could if necessary throw in CSS text-transform: uppercase. As this takes place entirely client side, your only problem may be the browser support.
<h:outputText value="#{item}" style="text-transform: uppercase" />
(note: this is just an example, the normal practice is to put styles in its own .css file which you load by <h:outputStylesheet>)
<h:outputText value="#{item}" styleClass="uppercased" />
I suppose the -solution with a converter is the cleanest and represents most how JSF is supposed to be used. Do you think so, too?
I'm a big fan of "Use the right tool for the job". Use JSTL tags to conditionally build the JSF component tree. Use JSF components to generate HTML. That's it. See also JSTL in JSF2 Facelets... makes sense?
This question already has answers here:
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
(3 answers)
Closed 5 years ago.
I'm having a massive problem getting an extremely simple task done in JSF. The problem: I have objects, who have aggregated properties that can vary in type from object to object. Depending on the type of the property, I want to use a different set of input fields.
The subtype components reside in frameworks and get loaded on demand. To this end, I use the following code:
<h:panelGroup id="zusatzdaten">
<fieldset class="clear">
<legend>#{tickerUI.ticker.tickerDescription.label}
(#{tickerUI.ticker.tickerDescId})
</legend>
<h:panelGroup rendered="#{tickerUI.editComponentName != null}">
<ui:include src="#{tickerUI.editComponentName}"/>
</h:panelGroup>
</fieldset>
</h:panelGroup>
The name of the component comes out of TickerUI, which is of #SessionScope. Now the dazzling bit: when it first loads, the correct subcomponent is displayed. However, when using a link in the navigation, which should lead to including a different component, the content is NOT updated! This results in an error, because the data is now a different subtype, but the form components are still from the previous one.
When going back from the error and clicking the link again, the correct component is displayed. I logged the value of editComponentName and the correct values are returned. This is very confusing. Why is including the wrong content when the getter returns the correct component name to the 's src attribute?
Help greatly appreciated.
Actually your problem is a classic view build vs view render time problem/misunderstanding. More specifically, the view is built on every new request and reconstructed from a previously saved state on postbacks. Later the view is rendered to produce HTML content.
Now, as <ui:include> is a tag handler, or in official terms a view build time tag, when you first request the page, its value attribute is evaluated, and the included page makes its way into the view. Upon postback, contrary to what you might expect, the incuded contents are already there, in the reconstructed view. So, it is an expected behaviour that you'll have the exact part of view rendered.
As to the solution, you could just simply include an exhaustive list of static includes that are wrapped in conditionally rendered <ui:fragment> JSF components. For simplicity, all content could be places within a container like <h:panelGroup> that's always rendered for ease of AJAX updates. The code could be assembled as follows:
<h:panelGroup id="ui">
<ui:fragment rendered="#{bean.condition1}">
<ui:include src="/path/to/file1.xhtml"/>
</ui:fragment>
...
<ui:fragment rendered="#{bean.condition_n}">
<ui:include src="/path/to/file_n.xhtml"/>
</ui:fragment>
</h:panelGroup>
A classical dilemma, it seems. BalusC's blog gave the solution for my case in the form of a configuration parameter in web.xml:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
I have 2 <h:panelGroup for conditional text display. When I run with id empty than this condition is executed fine #{empty personBean.person.id} and I see text in it. If I put <h2>#{buttonText}</h2> in panels than I see buttonText properly displayed in h2 tag.
Now Problem:
In below code if I put <h2>#{buttonText}</h2> at the end like below than I always get value Update member due to this I can not use value of buttonText anywhere in the page below. Someone tell me what to do?
<h:panelGroup rendered="#{empty personBean.person.id}">
<h1>Add Information</h1>
<i>Use the form below to add your information.</i>
<ui:param name="buttonText" value="Add member" />
</h:panelGroup>
<h:panelGroup rendered="#{not empty personBean.person.id}">
<h1>Update Information</h1>
<i>Use the form below to edit your information.</i>
<ui:param name="buttonText" value="Update member" />
</h:panelGroup>
<h2>#{buttonText}</h2>
I am unable to use <ui:param like I use <c:set var="buttonText" value="Add member" /> JSTL set variable.
The <ui:param> is not evaluated during view render time (ask yourself; does it necessarily generate any HTML?), but during view build time. So the rendered attribute isn't been taken into account at all and you effectively end up with both being interpreted and the latter one would always override the former one.
Technically, you'd need to "render" ("build" is a better term, but it reads a bit strange) it conditionally using a view build time tag such as <c:if>. However, in your particular construct it's better is to just check the very same condition in <ui:param>'s value and have only one of it instead of two:
<ui:param name="buttonText" value="#{empty personBean.person.id ? 'Add' : 'Update'} member" />
or just evaluate it directly there where you need it
<h2>#{empty personBean.person.id ? 'Add' : 'Update'} member</h2>
See also:
JSTL in JSF2 Facelets... makes sense? - not exactly your issue, but just to understand "view build time" versus "view render time" better.