Skip to main content

composite component with "for" attribute in jsf2.0 - is it possible?

12 replies [Last post]
maxqua72
Offline
Joined: 2010-03-31

Hi,

I would like to create a composite component like this:

where other_component_id is the id of an h:inputText, in order to render an image in case there are messages related to that client id.

I know FacesContext has getMessageList(clientId) to be used to check whether there are messages, but how to use that function in the composite component implementation?

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
digitalseraphim
Offline
Joined: 2008-04-30

I know that richfaces has a way to look up an element's id by the "simple" id, but I don't know if there is in straight JSF. it's #{rich:elementId('id')} I believe. might help you find it for whatever you are using.
------EDIT------
so, for history sake, I've left the above. the richfaces facelet function is actually rich:clientId(), but I found this page that explains how to do what you want. I had figured out how to do this once myself, but don't have the code handy.

http://illegalargumentexception.blogspot.com/2009/02/jsf-working-with-co...

vesuvius
Offline
Joined: 2007-06-02

Yup, it can be done using Java -- either by using [i]another[/i] Java-based custom component, or making our own component Java-based.

I just don't know if it can be done in a pure composite component, without any Java involved.

Of course, there's nothing wrong using Java. I actually like it more in certain cases. I'm simply curious whether there's [i]built-in[/i] functionality in JSF2 which allows us to perform component lookup by id (not by clientId) in a composite component.

vesuvius
Offline
Joined: 2007-06-02

Try the following:

[code]

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
xmlns:h="http://java.sun.com/jsf/html"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:ui="http://java.sun.com/jsf/facelets">












[/code]

It worked on GlassFish v3.

maxqua72
Offline
Joined: 2010-03-31

I updated the EL to 2.2 and your code works, but there is still something unclear to me.

I'm interested not in the message list belonging to a clientId but I would like to know if there is at least one message for that client id.

I tryed with:





but I got this error

javax.faces.view.facelets.TagAttributeException: /resources/mtc/message1.xhtml @17,70 test="#{facesContext.getMessageList(cc.attrs.for).size != 0}" For input string: "size"
at com.sun.faces.facelets.tag.TagAttributeImpl.getObject(TagAttributeImpl.java:324)
at com.sun.faces.facelets.tag.TagAttributeImpl.getBoolean(TagAttributeImpl.java:129)
at com.sun.faces.facelets.tag.jstl.core.IfHandler.apply(IfHandler.java:85)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:91)
at com.sun.faces.facelets.tag.composite.ImplementationHandler.apply(ImplementationHandler.java
..............

Caused by: java.lang.NumberFormatException: For input string: "size"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
........

I used also

but it doesn't work either. why?

I tried then using a bean with a function like this:
public boolean areThereAlarms(String clientId){
boolean retval = false;
// See if there are messages queued for the page
Severity severityLevel = getFacesContext().getMaximumSeverity();

if (null != severityLevel) {
List list = getFacesContext().getMessageList(clientId);
System.out.println("clientid = "+clientId + " "+list.size());
if(list != null){
if(! list.isEmpty()){
System.out.println("list ok");
retval = true;
}
}

}
return retval;
}

and



but the list is always empty because there is no match with the clientId. It works only if I use the complete name of the clientId ("j_idt10:j_idt85:j_idt86:j_idt87:"+clientId).
I don't undestand why.
In any case how can I get the complete id of the client from cc.attrs.for ? Is there any API I can use within the bean?

Message was edited by: maxqua72

Message was edited by: maxqua72

vesuvius
Offline
Joined: 2007-06-02

By all means, avoid using JSTL tags in JSF. Only use Facelets tags. This will save you a lot of trouble in the long run. (http://onjava.com/pub/a/onjava/2004/06/09/jsf.html -- pay special attention to the "Mixing JSF and Non-JSF Tag Libraries" section.)

You could try something like:

[code]


...


[/code]

The most important part in the snipped above is the [b]rendered[/b] attribute.

EDIT: Actually, the article above discusses the deficiencies of JSP as a JSF view handler. It doesn't discuss Facelets but I think the main idea to avoid JSTL still applies.

maxqua72
Offline
Joined: 2010-03-31

Thanks but it doesn't work:
Using


the output text is never displayed.
But if I use


it is ok.
How can I get the complete clientId?

vesuvius
Offline
Joined: 2007-06-02

Apparently, you've nested your component inside other parent components.

I don't know [i]the best[/i] solution, but I can give you some clues:

It might be best for you to put explicit ID's to all the parent components, and not to rely on JSF to generate the ID's. Thus, at least you can be sure that the ID's will be same every time. For example, the form could have an explicit ID:

[code]

...

[/code]

Then, if there are no additional nestings, the component ID should be something like "myForm:userNameInput" instead of "j_idt10:userNameInput". For each element in the path, you should provide an explicit ID.

Then, in the [b]for[/b] attribute of your custom component, provide the full ID:

[code]

[/code]

I know this is ugly but I don't know any other way.

Mind you, I'm not saying there's no other way. Perhaps there is. I just don't know it.

Maybe one of the gurus might drop a comment here...

maxqua72
Offline
Joined: 2010-03-31

Sorry, but it doesn't work:

items="${facesContext.getMessageList(cc.attrs.for)}" Error Parsing: ${facesContext.getMessageList(cc.attrs.for)}

using for instead of cc.attrs.for it is the same.

here is the piece of code I used just to try:



xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:composite="http://java.sun.com/jsf/composite">





cellpadding="5"
rendered="#{! empty facesContext.maximumSeverity}">




digitalseraphim
Offline
Joined: 2008-04-30

In what way doesn't it work? Are you getting an exception or is nothing showing? I see you don't have anything inside of the c:forEach tags. Did you try outputting something here? I think you want something like:






Where severity and detail are the two fields you actually want to display from msg.

-ds

maxqua72
Offline
Joined: 2010-03-31

I guess I understood why it doesn't work. I'm using tomcat 6 which hasn't got EL2.2 that's why I got the parsing error: I try removing the parenthesis and using

and the parsing error disappear (but that is not what I want).

digitalseraphim
Offline
Joined: 2008-04-30

I have an idea, but it's kind of a hack, so hopefully someone has a better idea, but I'll give it to you anyway. Create an Event scoped bean, with a Map field, where you override the get() to do your bidding:

/*bean fluff*/

  private Map facesMessageMap = new HashMap(){
    @Override
    public FacesMessage[] get(Object _key){
      String key = _key.toString();
      return FacesContext.getCurrentContext().getMessageList(key);
    }
  }

  public Map getFacesMessageMap(){return facesMessageMap;}

/*more bean fluff*/

Then, in your EL, you specify #{bean.facesMessageMap[cc.attrs.for]}

Give this a try. Did this off the top of my head, so you may have some errors you need to work through, but the idea is there.

-ds

digitalseraphim
Offline
Joined: 2008-04-30

This is purely a guess right now, as I don't have a way to test it ATM, but give this a try:


...

-ds