6 Replies Latest reply on Jul 26, 2008 7:50 PM by adambuckley.www.seamframework.org.adambuckley.net

    Using custom facelets taglib attributes in seam action.

    sbyrne.sb.ezftz.com

      I have the following custom Facelets tag:


      <span xmlns:s="http://jboss.com/products/seam/taglib">
          (#{test})
          <s:button styleClass="button" value="test"
              action="#{testManager.test(test)}" />
      </span>
      



      Which is properly registered and called like this:


      <mytags:test test="foo" />
      




      testManager refers to the following Seam component (package and imports omitted for brevity):


      @Name("testManager")
      @Scope(ScopeType.CONVERSATION)
      public class TestManager {
      
          @Logger
          private Log log;
      
          public void test( String id ) {
              if ( id == null ) {
                  log.info( "id is null" );
              } else {
                  log.info( "id:" + id.getClass().getName() + ":" + id.toString() );
              }
          }
      
      }
      



      The page renders with (foo) and a Button with the label test, which is as I expected. However, when I hit the button, my output is:


      id:java.lang.String:



      but I expected:


      id:java.lang.String:foo



      How do I pass a String to my tag and use it as a parameter for an action?

        • 1. Re: Using custom facelets taglib attributes in seam action.
          mail.micke

          Here is a wild guess


          
          <mytags:test test="#{'test'}" />
          
          



          I have no idea if that will make any difference :)

          • 2. Re: Using custom facelets taglib attributes in seam action.
            sbyrne.sb.ezftz.com

            Mikael Andersson wrote on Jul 14, 2008 16:34:


            Here is a wild guess

            
            <mytags:test test="#{'test'}" />
            
            



            I have no idea if that will make any difference :)



            No difference.

            • 3. Re: Using custom facelets taglib attributes in seam action.
              sjmenden

              I put your example in a test case and found the same thing.  Logically this should work, but as far as I can tell, the variable is not available to the EL variable resolver when the method url is created which looks like:


              testManager.seam?cid=1&actionMethod=testManager.xhtml%3AtestManager.test(test)&test=someId



              Whereas if I specify the literal string 'test in the xhtml like: test('test') then the resulting url is:



              testManager.seam?cid=1&actionMethod=testManager.xhtml%3AtestManager.test('test')&test=someId




              Which means that in the first case the test variable is either not resolved yet, or can't resolve, and if it is not resolved yet when the url is built, then that means it can't be resolved later on.


              I would suggest creating a JIRA so the devs can take a look. Either, the variable is not accessible intentionally as it is an inherited variable from another template, the scoping is not always straight forward in these scenarios, or, there could be a bug always.



              But, the workaround is quite easy, just use f:param:




              <s:button styleClass="button" value="test" action="#{testManager.test}">
                <f:param  name="test" value="#{test}"/>
              </s:button>





              @Name("testManager")
              @Scope(ScopeType.CONVERSATION)
              public class TestManager {
              
                  @RequestParameter
                  private String test;
                   
                  @Logger
                  private Log log;
              
                  public void test() {
                       log.info("@RequestParameter: " + test);
                  }
              
              }




              -Samuel

              • 4. Re: Using custom facelets taglib attributes in seam action.
                sbyrne.sb.ezftz.com

                Funny thing is that the variable is resolved if it is in the rendered attribute, just not in the action attribute.

                • 5. Re: Using custom facelets taglib attributes in seam action.
                  sjmenden

                  Well, that got me to thinking, if rendered works, h:commandButton should, and it does:



                  <h:form>
                    <h:commandButton value="test" action="#{testManager.test(test)}" />
                  </h:form>



                  Which then looks like it is an issue with how Seam/JBoss EL resolves the attribute.


                  -Samuel

                  • 6. Re: Using custom facelets taglib attributes in seam action.
                    adambuckley.www.seamframework.org.adambuckley.net

                    Hi there,


                    I am also using facelets tags in basically the same manner as Stephen above.


                    I am finding that using a s:link does not let me use action="#{productAction.selectProductFromFavorites(row.id)}" which is the problem described above.


                    But I am also finding that using s:link does not even propagate the @DataModelSelection, so this code won't work:


                    <s:link value="#{row.description}" action="#{productAction.selectProductFromFavorites}">



                    If I use a h:commandLink or an a:commandLink, then the @DataModelSelection works as expected.


                    Is this a bug?  Or is it intentional??  Is there a JIRA number for this?


                    My source code is shown below (the aim of which is to provide pagination and 'no rows found' message in a common place).


                    Thanks, Adam.



                    dataTable.xhtml


                    <ui:composition xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:r="http://richfaces.org/rich" xmlns:f="http://java.sun.com/jsf/core"
                         xmlns:s="http://jboss.com/products/seam/taglib" xmlns:h="http://java.sun.com/jsf/html" xmlns:a="http://richfaces.org/a4j">
                    
                         <r:dataTable id="#{tableId}" rowClasses="#{tableRowClasses}" var="row" rows="#{tableMaxRows}" value="#{tableData}" styleClass="box"
                              footerClass="#{empty tableData or tableData.size==0 or tableData.size > tableMaxRows ? 'whiteFooterRow' : 'hidden'}">
                    
                              <!-- Columns (and possibly header definition) go here, as specified by body of calling dataTable tag -->
                              <ui:insert />
                    
                              <f:facet name="footer">
                                   <r:columnGroup>
                                        <r:column styleClass="whiteFooterRow" colspan="2" rendered="#{tableData.size > tableMaxRows}">
                                             <r:datascroller style="float: right" pageIndexVar="pageIndex" pagesVar="pages" boundaryControls="hide" stepControls="hide" fastControls="show">
                                                  <f:facet name="pages">
                                                       <h:outputText style="whitespace: nowrap" value="#{pageIndex} of #{pages}"></h:outputText>
                                                  </f:facet>
                                             </r:datascroller>
                                        </r:column>
                    
                                        <r:column colspan="2" styleClass="emptyTable" rendered="#{empty tableData or tableData.size==0}">None available</r:column>
                                   </r:columnGroup>
                              </f:facet>
                         </r:dataTable>
                    </ui:composition>



                    WebContent/META-INF/enabler.taglib.xml


                    <!DOCTYPE facelet-taglib PUBLIC
                      "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
                      "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
                    
                    <facelet-taglib>
                         <namespace>http://www.conexa.com/enabler</namespace>
                         <tag>
                              <tag-name>dataTable</tag-name>
                              <source>tags/dataTable.xhtml</source>
                         </tag>
                    </facelet-taglib>



                    Snippet from ProductActionBean


                    @DataModel
                    private List<Product> favoriteProductList;
                    
                    @DataModelSelection("favoriteProductList")
                    private Product favoriteProductSelection = null;
                    
                    public void selectProductFromFavorites()
                    {
                         showSearchResults = false;
                         currentOrderItem.setProduct(favoriteProductSelection);
                    }



                    Snippet from product.xhtml


                    <!-- Favorites -->
                    <en:dataTable tableId="favoriteProductList" tableData="#{favoriteProductList}" tableRowClasses="#{productAction.favoriteRowClasses}" tableMaxRows="8">
                         <f:facet name="header">
                              <r:columnGroup>
                                   <r:column style="text-align: left">
                                        <h:outputText value="Favorites" />
                                   </r:column>
                    
                                   <r:column style="text-align: right">
                                        <s:link styleClass="boxTitleLink" value="Edit" view="/editFavorites.xhtml" propagation="join" />
                                   </r:column>
                              </r:columnGroup>
                         </f:facet>
                    
                         <r:column>
                              <a:commandLink value="#{row.description}" action="#{productAction.selectProductFromFavorites}" reRender="productResults,favoriteProductList" />
                         </r:column>
                    
                         <r:column style="text-align: right">
                              <a:commandLink action="#{productAction.addProductFromFavorites}" value="Add" reRender="currentOrderItems" />
                         </r:column>
                    </en:dataTable>