Get client ID of composite component itself for usage in JavaScript - jsf

I have got some interesting issue for you. I am creating a composite component. I know, that I can use ui:param for storing value and reuse it. But what if I store to this variable some relative value (#{component.namingContainer.clientId}) and want to reuse it as a constant? It is difficult to explain - here you have my code:
<ui:param name="rdfaComp" value="#{component.namingContainer.clientId}"/>
This is in the beginning of the page - I want to store exactly this ID and then use nothing else by this variable. But later if I reuse it inside elements with own IDs, it is bad. It is interesting, what happens - JSF doesn't take the same value, but a relative one. It reads once more #{component.namingContainer.clientId}, not the fixed value.
How to solve this, could you help me, please? THanks a lot.
UPDATED
There is still one important condition: the variable rdfaComp have to be available immediately, because I reuse it in a Javascript function (on the same page). Like this:
<h:commandButton onclick="return selectText('#{rdfaComp}:editor', ...
I am afraid, it is necessarry to use relative ID chains like this: #{component.namingContainer.parent.namingContainer.parent.clientId} etd.
But it is really awful. Is there another solution?

The <ui:param> indeed merely creates an alias and the EL expression is still deferred and evaluated on every access in the very same context as where it's been referenced (and thus not where it's been declared! that explains your concrete problem). Besides, the <ui:param> is designed to be used on <ui:include>, <ui:composition> and <ui:decorate> only.
Use <c:set> instead. It's capable of immediately evaluating an EL expression and storing its result in either request, view, session or application scope via the scope attribute.
<c:set var="rdfaComp" value="#{component.namingContainer.clientId}" scope="request" />
Update: you actually wanted to get the client ID of the composite component itself, here's how you can get it:
<c:set var="rdfaComp" value="#{cc.clientId}" scope="request" />

It is solved - and I must apologise once more :-). I didn't describe correctly the issue - what I really wanted to do. I just wanted to work with the full client ID of the composite component. Finally I found a solution: #{cc.namingContainer.clientId}
Thanks anyway, your answers were very helpful!

Related

EL variable resolution in JSF: is there a way to control when it happens?

I often face the following problem. I have a JSF application and a facelet where I write EL expressions, like this:
<h:outputText value="#{myBean.foo}">
As long as myBean, as a variable, has a life long enough, there's no problem to evaluate myBean.foo at any given time, but if myBean is a variable that references some bean within a short period of time, when myBean.foo is evaluated it might be too late, so that JSF complains that myBean resolves to null. This is something well-known, but the problem is that it is not clear to me what to expect in different situations.
Concrete example n. 1: if you try the following with PrimeFaces OrderList:
<p:orderList value="#{bean.myValue}" var="item">
<p:column>
<p:commandLink action="#{bean.doSomething(item)}" />
</p:column>
</p:orderList>`
This is not going to work, because when doSomething is called, the item variable is no longer defined (although the object it references is still alive) and hence it's resolved to null. It's a known issue. However the same pattern works fine with <p:dataTable>, for instance. Anyway, I'm not interested right now in this specific problem, I just want to explain my doubt.
Concrete example n. 2: I have written a composite component with a backing bean. The backing bean extends UINamingContainer and uses its StateHelper to retain a model object. This composite allows to write child tags and I would like to write something like this:
<myns:myCc var="myVar">
<h:inputText value="#{myVar.foo}" />
</myns>
With "myVar" I want to give a name to the model object. To make this work, I tried to store the model object in the request map at the beginning of encodeChildren method and remove it afterwards: this works for rendering, but if I then process the input with a commandButton action, it does not work because when the action gets executed it says that myVar can't be resolved: in other words, it tries to resolve the entire expression too late. I then tried to "permanently" save the model object in the view scope map, but it doens't work either. However, if I change this to:
(assuming modelObject is the property field in the backing bean that stores my model object)
it works. So, it is not a problem in my model, but in the way I try to make the model object available to EL expressions for child tags.
Concrete example n. 3: I often use the <ui:param> tag to give beans a shorter name and to ease templating. For instance:
<ui:param name="bean" value="#{longNamedAndPageSpecificBean}" />
So that, in the remainder of the page I can just use #{bean.foo} instead of #{longNamedAndPageSpecificBean.foo}. This works fine even for actions passed to command buttons. However, if I pass a method expression like #{bean.myActionMethod} to a composite component attribute declared with method-signature, when this method expression is actually invoked I receive an error that bean resolves to null... The reason why it works in one case (with commandButton actions) and not in the other (with actions used by the composite component) is a big source of confusion for me.
I would appreciate if someone can help me to understand better this JSF aspect and suggest better approaches/workarounds with the aforementioned concrete examples.
Your question looks too large, but i could say that, during the build time only Session and request scoped values are avaiaible.
The same thing is true for the Execution phase.
Only the render phase should ensure the avaibility of temporal vars "myVar".
The best way to understand what its realy hapening is to debug because its depends on the component implementation

EL function not found in validator attribute

El function cannot be found using within validator attribute, which is dependent on dynamic or repeated values?
Function 'el:min' not found
#{el:min(a + b, c)}
<f:validateLongRange maximum="#{el:min(foo.bar, 10)}"/>
Just printing out the value is working where it is not working in the validator.
The error message Function 'el:min' not found was so misleading.
The problem was never the construct but it was an underlying NullPointerException on the nested property.
Since in one case the value was depending on a different component selection it was updated via ajax and the default value was null. Since the default value was null this misleading exception was thrown.
The value was a nested property, so it was not catched within the el function
Solution: disable the validator on default
<o:validator validatorId="javax.faces.LongRange" maximum="#{el:min(foo.bar, 10)}"
disabled="#{foo eq null}"/>
This construct should work just fine. The problem is most likely the scope of the variables which you've there and the timing (i.e. when do you need them? when are they "behind the scenes" changed?).
You need to understand that taghandlers like <f:xxx> run during view build time (like JSTL <c:xxx>). So their attribtues are resolved during view build time and would be filled with bean's default values. Perhaps you're performing some business logic on them while submitting the form and expecting that they would be reflected into the taghandler attribute. But this is not true. They were already evaluated during view build time and won't re-evaluate the values during processing the form submit.
If this is indeed the case, then you've basically the same problem which is already outlined and answered with various possible solutions in this answer: How to set converter properties for each row of a datatable? Apart form homegrowing a Validator for this, you could use OmniFaces <o:validator> for this:
<o:validator validatorId="javax.faces.LongRange" maximum="#{el:min(a + b, c)}" />

Jsf always remove last element from ArrayList

I have an ArrayList in a backing bean and his rendering in JSF page with c:forEach. When iI remove the ArrayList element by index, jsf, no matter what index is, always removes the last element. Why happening this?
Remove button in JSF is :
<a4j:commandButton immediate="true" action="#{bean.removeEntry}" ...
So i use immediate attribute. I think problem is because immediate skips Apply request phase in JSF Life Cycle. Is possible?
If yes, than how run Apply request phase in this case ?
Are you using Facelets (.xhtml pages)? If so, you may be running into some common misconceptions about JSTL tags like <c:foreach>. Here's a good article on it:
https://rogerkeays.com/jsf-c-foreach-vs-ui-repeat
Basically, <c:foreach> is processed only when the view is initially built; it does not become part of the component tree, and can have some behavior you don't expect when the backing collection is changed. You may be better off using <ui:repeat> instead.
little more code would have helped, but immediate on command button is basically used for navigating away from current page as actionlistener or action will execute in apply request phase, typical case cancel button. This means you will not get updated value there.
If your logic depends on some other uiinput make that immediate and you can hook things in valuechangelistener.
But I doubt what you are trying to achieve can be done in better way, have a look at this link # SO
I was having the similar issue. I was using 'tr:iterator' to iterate over ArrayList'<'Customer'>'(); 'ui:repeat' solved my problem.
Thanks.

Why EL gives me the wrong object as parameter between parenthesis?

Here's the situation:
In a rich:dataTable in an a4j:form, i create a a4j:commandLink to select the values and pass it to the bean with the jboss el action syntax
action="#{bean.myaction(myparameter)}"
This works without problem.
But If I re-render the form to filter the datatable with an ajax call, when I select the value, it gives me the wrong results: the index from the selection, but the data from before the filtering.
Any ideas?
Thank you Zack for giving me the right solution in only 5 minutes.
I think passing parameter in the action between parenthesis is more elegant but, hey: this works. :)
Thank you a lot.
P.s. I'm editing the title too.
Try using:
<a4j:commandLink action="#{bean.myaction}">
<f:param name="myparameter" value="paramValue" />
</a4j:commandLink>
and then access that parameter in your action via the requestParameter("myparameter") through the FacesContext.
As a side-note, this isn't jboss EL, it's unified expression language (EL). It's just a feature of JSP/JSF in general, as specified by Sun.
In addition to the Zack's answer, I would say that if you need to extend the EL expressions in order to have the ability to call method with parameters, you can use the EL Functors library:
action="#{bean.myaction$[myparameter].action}"
Is your datatable populated using a Collection annotated with #DataModel ? If so try removing it from the context when filtering so that it gets re-requested.
eg.
//In filter method
Contexts.removeFromAllContexts("yourDataModelCollection");
Putting the dataTable in a <a4j:region> worked for me. This way, you can still use JBoss EL parameters.

parameterised jsp:includes of stripes actions?

I've been trying to solve this, and have been getting stuck, so I thought I'd ask.
Imagine two ActionBeans, A and B.
A.jsp has this section in it:
...
<jsp:include page="/B.action">
<jsp:param name="ponies" value="on"/>
</jsp:include>
<jsp:include page="/B.action">
<jsp:param name="ponies" value="off"/>
</jsp:include>
...
Take it as read that the B ActionBean does some terribly interesting stuff depending on whether the "ponies" parameter is set to either on or off.
The parameter string "ponies=on" is visible when you debug into the request, but it's not what's getting bound into the B ActionBean. Instead what's getting bound are the parameters to the original A.action.
Is there some way of getting the behaviour I want, or have I missed something fundamental?
So are you saying that in each case ${ponies} on your JSP page prints out "on"?
Because it sounds like you are confusing JSP parameters with Stripes action beans. Setting a JSP parameter simply sets a parameter on that JSP page, that you can reference as shown above, it doesn't actually set anything on the stripes action bean.
The reason that this wasn't working was because of massaging done by our implementation of HttpServletRequest.
It works fine with the "normal" implementation.

Resources