2009/5/24 Dan Allen <dan.j.allen@gmail.com>
> I think you are running into the "composite component gets an id in the component tree but is not represented in the rendered output problem". I've been
> discussing this problem in private mailings with Ryan and Andy...and now that you have observed it too I think it is something we need to address.

I'm not sure if we are talking about the same thing. Here's my situation. I have a menu with an image:

           <h:panelGrid columns="2">
             <div class="zoomPrompt">
               #{msgs.zoomPrompt}
             </div>
     
             <h:selectOneMenu id="menu"
                  value="#{cc.parent.attrs.location.zoomIndex}"
                  style="font-size:13px;font-family:Palatino">
     
                <f:ajax render="image"/>
                <f:selectItems value="#{places.zoomLevelItems}"/>
              
                <h:graphicImage id="progressbar" style="display: none"
                  library="images" name="orange-barber-pole.gif"/>
             </h:selectOneMenu>
           </h:panelGrid>

           <h:graphicImage id="image" url="#{cc.parent.attrs.location.mapUrl}"
            style="border: thin solid gray"/>

See the attached 001.png to see what it looks like.

When the user changes the zoom level in the menu, the zoom index is updated on the server, and when the ajax call returns, the image is updated due to the render attribute of the <f:ajax> tag. That works fine (thanks, Ryan!).

Ok, so now I want to encapsulate the zoom prompt and menu in a composite component, so I can just do this:

           <places:zoomLevelControl/>

           <h:graphicImage id="image" url="#{cc.parent.attrslocation.mapUrl}"
            style="border: thin solid gray"/>

Here's what that component looks like:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:composite="http://java.sun.com/jsf/composite">
   
  <!-- INTERFACE -->
  <composite:interface>
  </composite:interface>
       
 <!-- IMPLEMENTATION -->
 <composite:implementation>
   <h:outputScript library="javascript/prototype" name="prototype-1.6.0.2.js"/>
   <h:outputScript library="components/places" name="util.js"/>
    
   <h:panelGrid columns="2">
     <div class="zoomPrompt">
       #{msgs.zoomPrompt}
     </div>

     <h:selectOneMenu id="menu"
          value="#{cc.parent.attrslocation.zoomIndex}"
          style="font-size:13px;font-family:Palatino">

       <f:ajax render="image"/>
       <f:selectItems value="#{places.zoomLevelItems}"/>
      
       <h:graphicImage id="progressbar" style="display: none"
         library="images" name="orange-barber-pole.gif"/>
      
     </h:selectOneMenu>
   </h:panelGrid>

 </composite:implementation>   
</html>

All I've done is cut the zoom prompt and menu from the original file, and pasted it into zoomLevelControl.xhtml.

However, now when I change the zoom level menu, I get an error:

    <f:ajax> contains an unknown id 'image'

If I remove the <f:ajax> tag from places:zoomLevelControl.xhtml, so the page can load without an error, there is actually a component whose id is image (at least relative to the naming container in which it resides). Here's the HTML:

<img id="form:j_id1186681689_16ef8569:0:j_id1186681689_16ef8513:j_id-1105909415_41ead6fe:image" src="http://gws.maps.yahoo.com/mapimage?MAPDATA=2Y3iJ.d6wXVASQ9jSqfHLeKEax1dy5SAHJNemUUlZBYuvpfIWQ9MKbXJ.SoEDpCUAAQYuF9hQvb7E.gRWJG90677SNjMOa.AbNyqN.J66qv_y8Mo0DU60U9Nph2E4lfj63DVp9y5MGYMeBiSzuKOhRs-&amp;mvt=m&amp;cltype=onnetwork&amp;.intl=us&amp;appid=gaspe_geary&amp;oper=&amp;_proxy=ydn%2Cxml" style="border: thin solid gray" />


The problem is, while the username id is represented in the tree (as the composite component), it's not represented in the rendered output. The composite component is a non-rendering container. That's why the update script cannot locate the DOM node to update.

To get it to work, I had to represent the id of the component template somewhere in my template...most naturally on the wrapping div.

<div class="entry" id="#{cc.clientId}">
  <comp:insertChildren/>
</div>

I wasn't able to get something like that to work for my situation.


Is this an unwritten rule? Or should the id automatically be assigned to the first child of the composite component. I can see people getting easily confused over this.

Developers are going to trip all over this subtlety, I'm sure of it.

Oh yeah, absolutely. I'm certain that refactoring an ajaxified composite component in the manner I've described above will be a common occurrence. I'm not sure what the underlying technical reasons are for not being able to do that refactoring, but IMO, it's got to work, or composite components will loose much of their value.


david


On Sat, May 23, 2009 at 1:26 PM, David Geary <clarity.training@gmail.com> wrote:
I have a view composed of a template, and a handful of compositions. In one of those compositions, I want to trigger an ajax request with f:ajax, and I want to render a component in a different composition (but ultimately in the same page). That doesn't seem to work.

To be a little more explicit, I have a menu, implemented with a composition, from which I launch an ajax request. When the request returns, I want to render a single component in another composition. However, when I try to do that, JSF complains that the component id cannot be found, when in fact, the component is in the page, and is even in the same naming container.

I suspect that f:ajax is looking for the component id before the page is fully constructed, and therefore only sees components in the same composition.

This should work, correct? If I cannot effectively use ajax across compositions in the same page, then that makes templating a lot less attractive.

Thanks,


david

-Dan

--
Dan Allen
Senior Software Engineer, Red Hat | Author of Seam in Action

http://mojavelinux.com
http://mojavelinux.com/seaminaction
http://in.relation.to/Bloggers/Dan

NOTE: While I make a strong effort to keep up with my email on a daily
basis, personal or other work matters can sometimes keep me away
from my email. If you contact me, but don't hear back for more than a week,
it is very likely that I am excessively backlogged or the message was
caught in the spam filters.  Please don't hesitate to resend a message if
you feel that it did not reach my attention.