6 Replies Latest reply on Aug 11, 2008 4:45 PM by Greg Zoller

    Iteration and s:link

    Greg Zoller Newbie
      Hello,

      I'm trying, unsuccessfully, to have an editable list of strings (email addresses).  Each string is an s:link which when clicked will call an action method.

      I can render the list as desired and when the s:link is clicked my action method is called, but... no value is passed so in the method I don't know what was clicked.

      Any ideas how I can accomplish this desired behavior?

      Code snippet:

           <a4j:region>
                <a4j:outputPanel id="asn">
                     [<h:outputText value="#{cartMgr.cart.asnEmails[0]}"/>
                     <a4j:repeat first="1" value="#{cartMgr.cart.asnEmails}" var="email">
                          , <s:link style="padding-left:3px;" value="#{email}"
                                    action="#{cartMgr.cart.editEmail(email)}">
                          </s:link>
                     </a4j:repeat>]
                </a4j:outputPanel>
                <rich:inplaceInput id="sand" defaultLabel="(add more)"
                     value="#{cartMgr.cart.emailSandbox}">
                     <a4j:support event="onviewactivated" action="#{cartMgr.cart.addEmail}" reRender="asn,sand"/>
                </rich:inplaceInput>
           </a4j:region>


      Now my Java action method:

           public void editEmail(String emailAddr) {
      System.out.println("ONE: "+emailAddr);
                int pos = asnEmails.indexOf(emailAddr);
      System.out.println("POS: "+pos);
      ...

      When run the output shows no value for emailAddr even though there is a value displayed on the screen for the link. 

      Any ideas?  Thanks in advance.
      Greg
        • 1. Re: Iteration and s:link
          Daniel Hinojosa Master

          Can we see what cart manager and cart look like?

          • 2. Re: Iteration and s:link
            Greg Zoller Newbie

            Here's a version of this behavior in two files.  The actual code is huge, so I can recreate this behavior in small form here--compressed app logic into the manager class.


            XHTML:


                      <h:form>
                          <rich:panel header="Emails">
                                EMAILS:
            
                                <a4j:outputPanel id="wow">
                                <a4j:repeat id="rep" value="#{mgr.emails}" var="email">
                                     <s:link value="#{email}" action="#{mgr.edit(email)}" /><br/>
                                </a4j:repeat>
                                </a4j:outputPanel>
                                
                                <br/>
                                <rich:inplaceInput 
                                      defaultLabel="(add more)"
                                      selectOnEdit="true"
                                       value="#{mgr.scratch}">
                                      <a4j:support event="onviewactivated" action="#{mgr.addEmail()}" reRender="wow" />
                                 </rich:inplaceInput>
                          </rich:panel>
                      </h:form>
            




            Manager Class:



            @Name("mgr")
            @Stateful
            @Scope(ScopeType.SESSION)
            public class ManagerBean implements Manager {
            
                private HtmlInplaceInput emailRef;
                private UIRepeat repeater;
                 private List<String> emails = new ArrayList<String>();
                 private String scratch="Hey";
                private Set<Integer> keys = null;
                
                public Set<Integer> getKeys() {
                    return keys;
                }
            
                public void setKeys(Set<Integer> keys) {
                    this.keys = keys;
                }
                
                 public List<String> getEmails() { return emails; }
                 
                 public void addEmail() {
                      System.out.println("ADD!" +scratch);
                      emails.add(new String(scratch));
                      scratch = null;
                 }
            
                 public String getScratch() {
                      return scratch;
                 }
            
                 public void setScratch(String scratch) {
                      this.scratch = scratch;
                 }
                 
                 public void edit(String index) {
                      System.out.println("EDIT INDEX: " + index);
                 }
                 
                 @Remove @Destroy
                 public void destroy() {}
            }
            



            The add/display part is working but when I click on the links inside my repeat clause nothing is passed to mgr.edit().  How can I pass in the one selected?


            Ultimately I will make these edit fields, not links so the user can edit addresses in the list.  For now I'll rig the s:link to simply delete the selected address from the list.


            I saw some complex examples using binding but then read something in the Seam docs that suggested binding wasn't desirable--didn't work with conversations or something.  Don't really understand all the nuances of binding and the examples I tried to emulate died w/exceptions (i.e. binding the a4j:repeat to a UIRepeat object, etc.).  Is that what I'm going to need here to get the desired behavior?


            Thanks for any advise.
            Greg

            • 3. Re: Iteration and s:link
              Daniel Hinojosa Master

              Oh, yeah! We had this a few days ago...try putting a @DataModel annotation on the email list.

              • 4. Re: Iteration and s:link
                Shervin Asgari Master

                Try to do like this:


                You create your s:link with f:param


                <s:link view="/MyHome.xhtml" value="Choose" action="#{someManager.choose}">
                    <f:param name="organisationId" value="#{org.organisationId}"/>
                </s:link>




                And then in your stateful bean:


                @RequestParameter
                private String organisationId;




                This will then be injected and you can get it from your action.


                Hope this helps

                • 5. Re: Iteration and s:link
                  Greg Zoller Newbie

                  Tried this approach and came up getting null value for the parameter.



                  <s:link style="padding-left:3px;" value="#{email}" 
                       action="#{cartMgr.cart.selectEmail}">
                       <f:param name="emailId" value="#{email.id}"/>
                  </s:link>




                  Then in my Java code for cart



                  @RequestParameter
                  private Integer emailId;
                  ...
                       public void selectEmail() {
                            System.out.println("SELECTED EMAIL: " + emailId);
                       }




                  In my EmailAddress object (email's type) I have a trivial id generator:


                       private static int idCount = 0;
                       
                       private Integer id = new Integer(idCount++);
                       public Integer getId() { return id; }
                  



                  When run my output statement comes back w/NULL. Any ideas why?  ALso tried String data type for id but that didn't matter.  I'll also try the DataModel approach Daniel suggested.


                  Thanks,
                  Greg

                  • 6. Re: Iteration and s:link
                    Greg Zoller Newbie

                    Hang on, ya'll.  My bad.  The @RequestParameter is working.  I was trying to inject it into an object that wasn't a Seam component.  D'oh!  Fixed that up and we're working great.


                    Thanks a million for the help and I'll also keep the DataModel approach in mind as well as that may be a good way to handle another issue I'm working.


                    Greg