>From: Richard Wallace <[EMAIL PROTECTED]> 
>
> Hello again, 
> 
> I'm trying to figure out how to use the Tomahawk updateActionListener in 
> Clay. The idea being that you can attach an action listener to a 
> commandLink and when that specific link is clicked a value will be set 
> on a given property of a backing bean. In JSP it would look something like: 
>
><h:commandLink action="go_country">
>  <h:outputText value="#{country.name}" />
>  <t:updateActionListener property="#{selectCountryBackingBean.country}"
>                value="#{country.id}" />
></h:commandLink>
> 
> I'm trying to do something like this in Clay. I was trying to use the 
> Tomahawk component but it seems there is actually alot being done in the 
> JSP tag code to take the property and value and creating value bindings 
> from them and setting them on the underlying component, rather than 
> having the component itself figure that stuff out. So it's not easily 
> reused in Clay. 
> 
> So, my question is has anyone tried this before and if so what, if 
> anything, did you figure out? Should I just create my own component 
> based on the one in tomahawk but with the necessary code moved into the 
> component rather than the tag class (and then give the code back to 
> MyFaces, of course)? 
> 
> Any other suggestions? 
>

I can think of a couple ways to handle this.  The fist would be to bind the 
target 
component to a managed bean and assign the action listener in code.  From 
what I understand this will be easier in JSF 1.2 because action listeners, 
converters and validators will have binding capabilities.

The most elegant way to handle this using clay would be to create a custom 
action creation command that's registered in the chain the build the component 
tree.  Clay uses common chains to build the component tree so you can register 
"interceptors" to handle things that don't fit into the normal processing.  
This was 
a feature that Ryan requested.

(http://svn.apache.org/viewcvs.cgi/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/component/chain/shale-clay-config.xml?rev=359113&view=log)

I created a simple ping/pong example in the tomahawk clay example project that 
I have not made time to finish.

First you will want to register a new catalog in the WEB-INF/chain-config.xml

 <catalog               name="clayCustomization">
    <chain               name="preprocessAddActionListener">
         <command      
className="org.apache.shale.examples.UpdateActionListenerCommand" />    
    </chain> 
 </catalog>

Next you need to create the custom command.  In this example I just extended 
the 
CreateActionListener command.

public class UpdateActionListenerCommand extends CreateActionListenerCommand {
 public boolean execute(Context context) throws Exception {
        boolean isFinal = false;
        
        ClayContext clayContext = (ClayContext) context;
        if (clayContext == null)
            throw new NullPointerException(messages
                    .getMessage("clay.null.clayContext"));
                
        ComponentBean displayElement = clayContext.getDisplayElement();
        if (displayElement == null)
            throw new NullPointerException(messages
                    .getMessage("clay.null.componentBean"));
                
        FacesContext facesContext = clayContext.getFacesContext();
        if (facesContext == null)
            throw new NullPointerException(messages
                    .getMessage("clay.null.facesContext"));
  
  //is this the type we want to intercept
  if (!displayElement.getComponentType()
    
.equals("org.apache.myfaces.custom.updateactionlistener.UpdateActionListener")) 
     return isFinal;
  
  // let the super create the action listener and assign to 
  // the child 
  isFinal = super.execute(context);
  if (isFinal)
     return true;
  
  UpdateActionListener listener = (UpdateActionListener) clayContext.getChild();
  
  // assign the custom properties
  AttributeBean sourceAttr = displayElement.getAttribute("valueBinding");
  AttributeBean targetAttr = displayElement.getAttribute("propertyBinding");
  AttributeBean converterAttr = displayElement.getAttribute("converter");
  
  ValueBinding vb = 
facesContext.getApplication().createValueBinding(sourceAttr.getValue());
  listener.setValueBinding(vb);
  
  vb = facesContext.getApplication().createValueBinding(targetAttr.getValue()); 
 
        listener.setPropertyBinding(vb);
  
  if (converterAttr.getValue() != null) {
     Converter converter = 
facesContext.getApplication().createConverter(converterAttr.getValue());
     listener.setConverter(converter);
  }
  
  isFinal = true;
  return isFinal;
 }
}

Now you need to create some clay xml configurations:
   <component jsfid="t:updateActionListener" 
             
componentType="org.apache.myfaces.custom.updateactionlistener.UpdateActionListener">
     <attributes>
      <set name="propertyBinding" bindingType="None">
         <description>Target EL value binding.</description>
      </set>
      <set name="valueBinding" bindingType="None">
         <description>Source EL value binding.</description>
      </set>
      <set name="converter" bindingType="None">
         <description>Converter id for conversion of the source to the 
target</description>      
      </set>
        </attributes>
   </component> 
   
   
  <component jsfid="pingAction" extends="commandLink">
      <actionListener jsfid="t:updateActionListener">
         <attributes>
             <set name="propertyBinding" value="#{pong.id}"/>
             <set name="valueBinding" value="#{ping.id}"/>
             <set name="converter" value="javax.faces.Integer"/>
         </attributes>    
      </actionListener>
  </component> 
   
  <component jsfid="pongAction" extends="commandLink">
      <actionListener jsfid="t:updateActionListener">
         <attributes>
             <set name="propertyBinding" value="#{ping.id}"/>
             <set name="valueBinding" value="#{pong.id}"/>
             <set name="converter" value="javax.faces.Integer"/>
         </attributes>    
      </actionListener>
  </component> 

Then I created a simple ping and pong managed bean.  The shale annotations 
are really nice. 

@Bean(name = "pong", scope = Scope.SESSION)
public class Pong {
 private Integer id = new Integer(0);
 public Integer getId() {
  return id;
 }
 public void setId(Integer id) {
  this.id = id;
 }
}


Finally, a clay full html view:

<html>
   <head><title>Ping Pong</title>
      <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" 
/>  
   </head>
   <body>
      <form>
          Ping:<input type=text value="#{ping.id}" 
converter="javax.faces.Integer">
          <input type=submit value="To Pong" jsfid=pingAction><br/>
          
          Pong:<input type=text value="#{pong.id}" 
converter="javax.faces.Integer">
          <input type=submit value="To Ping" jsfid=pongAction>          
      </form>
   </body>
</html>

 
> Thanks, 
> Rich 

Gary

> 
> --------------------------------------------------------------------- 
> To unsubscribe, e-mail: [EMAIL PROTECTED] 
> For additional commands, e-mail: [EMAIL PROTECTED] 
> 

Reply via email to