4 Replies Latest reply on Sep 9, 2009 4:45 PM by luxspes

    s:link and ui:repeat, a4j:repeat or c:forEach

    shadowdz

      Hi all,


      I have a 'navigation-tree' on my page which is genrerated by a xml file. In the xml I want to provide the posibility to specify url parameters.


      So in my xhtml i have code like this:



      
      <rich:tree
      
          <rich:treeNode 
      
            type="VIEWID">
      
             <s:link value="#{item.label}" view="#{item.viewID}">
      
                         <c:forEach items="#{item.parameterList}" var="param">
      
                             <f:param name="#{param.name}" value="#{param.value}" />
      
                         </c:forEach>
      
                </s:link>
      
           </rich:treeNode>
      
      </rich:tree>
      
      



      The s:link with c:forEach is working outside a rich:tree. I have tried ui(a4j):repeat. Can anybody provide me with a hint wat I can do, or what I have missed in the richfaces or seam documentation? Or any hints how I can manage this problem?


      By the way the same happens with h:outputLink or h:commandLink


      Greetings

        • 1. Re: s:link and ui:repeat, a4j:repeat or c:forEach
          stephen

          IMHO neither loop tag can work here:
          foreach is evaluated while building the component tree, so it can't access the item variable at that time.
          ui:repeat iterates over a single component, but that won't have any effect, because the f:param is evaluated by the parent component, which will see only a single f:param.


          Maybe something like this will work:



          <s:link value="#{item.label}" action="#{someHelperBean.gotoTreeNode(item)}/>



          where the gotoTreeNode can programmatically setup required parameters in page or conversation context and return an outcome depending on item.viewID.


          Or maybe use both view and action attributes on the s:link and let the action simply transfer the parameters.


          Tricky...


          What really is missing is a JSF tag like


          <f:params list="#{paramList}" var="param" name="#{param.name}" value="#{param.value}"/>



          Too bad you can't even write such a tag yourself, because the components that are decorated by f:param all contain code like child instanceof UiParameter.
          So much for good object oriented design.


          Maybe anybody else has a solution?


          • 2. Re: s:link and ui:repeat, a4j:repeat or c:forEach
            szimano.szimano.szimano.org

            There's a little workaround we found for this, so i'd like to share.


            We (or rather Adam Warski ;-) ) have specified in our taglib two functions


                <function>
                    <function-name>makeParamsName</function-name>
                    <function-class>com.vocado.frontend.jsf.Parameters</function-class>
                    <function-signature>java.lang.String makeParamsName(java.util.SortedMap)</function-signature>
                </function>
                <function>
                    <function-name>makeParamsValue</function-name>
                    <function-class>com.vocado.frontend.jsf.Parameters</function-class>
                    <function-signature>java.lang.String makeParamsValue(java.util.SortedMap)</function-signature>
                </function>
            



            the source class is


            package com.vocado.frontend.jsf;
            
            import java.util.Map;
            import java.util.SortedMap;
            import java.net.URLEncoder;
            import java.io.UnsupportedEncodingException;
            
            /**
             * Functions to create a link/button with variable (dynamic) parameters.
             * Usage is quite simple - you just need a SortedMap of your parameters.
             * Then, in the .xhtml, you need to have:
             * {@code <f:param name="{v:makeParamsName(parameterMap)}" value="{v:makeParamsValue(parameterMap)}" />} 
             * @author Adam Warski (adam at warski dot org)
             */
            public class Parameters {
                 /**
                  * Constructs a name for the pseudo-parameter tag, with which you can have dynamic parmeters.
                  * Creates a string:
                  * key1=value1&key2=value2&key3=value3&...&keyN
                  * where all values are url-encoded with UTF-8.
                  * The value of the last key will be appended by the value of the parameter.
                  * @param map Map, from which to construct the name of the pseudo-parmaeter.
                  * @return Name of the pseudo-parameter tag.
                  */
                 public static String makeParamsName(SortedMap<Object, Object> map) {
                      StringBuilder nameSB = new StringBuilder();
            
                      if (map.size() == 0) {
                           return null;
                      }
            
                      Object lastKey = map.lastKey();
                      for (Map.Entry<Object, Object> entry : map.entrySet()) {
                           Object key = entry.getKey();
                           nameSB.append(key);
                           if (!lastKey.equals(key)) {
                                nameSB.append("=");
                                nameSB.append(encode(String.valueOf(entry.getValue())));
                                nameSB.append("&");
                           }
                      }
            
                      return nameSB.toString();
                 }
            
                 /**
                  *
                  * @param map Map, from which to construct the value of the pseudo-parameter.
                  * @return Value of the pseudo-parameter tag: the last value of the map.
                  */
                 public static String makeParamsValue(SortedMap<Object, Object> map) {
                      if (map.size() == 0) {
                           return null;
                      }
            
                      return String.valueOf(map.get(map.lastKey()));
                 }
            
                 private static String encode(String toEncode) {
                      try {
                           return URLEncoder.encode(toEncode, "UTF-8");
                      } catch (UnsupportedEncodingException e) {
                           return toEncode;
                      }
                 }
            }
            


            So now, whenever we need to pass multiple parameters without using any iteration inside JSF you have to provide a sorted map with parameters (here just called parameters) and invoke by


             <s:link ...> 
               <f:param name="#{v:makeParamsName(parameters)}" value="#{v:makeParamsValue(parameters)}" />
             </s:link>
            



            Hope it helps,


            Tomek
               

            • 3. Re: s:link and ui:repeat, a4j:repeat or c:forEach

              Daniel Zwicker wrote on May 26, 2008 12:02:


              Hi all,

              I have a 'navigation-tree' on my page which is genrerated by a xml file. In the xml I want to provide the posibility to specify url parameters.

              So in my xhtml i have code like this:

              The s:link with c:forEach is working outside a rich:tree. I have tried ui(a4j):repeat. Can anybody provide me with a hint wat I can do, or what I have missed in the richfaces or seam documentation? Or any hints how I can manage this problem?

              By the way the same happens with h:outputLink or h:commandLink

              Greetings


              That is the wrong approach for rich:tree (but it is the right approach for other richfaces controls) for the rich:tree the right approach is to use a rich:recursiveTreeNodesAdaptor inside the rich:tree. See an example in this page.


              Please vote for RF-4128 to make all this more consistent (it asks for the same programming model for all tree/recursive controls).


              And remember, this kind of question is for the Richfaces Forum

              • 4. Re: s:link and ui:repeat, a4j:repeat or c:forEach

                Mmmm, nevermind, I think I understood your post incorrectly, what you want is a dynamic parameter list for s:link