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

    Iteration and s:link

    Greg Zoller Newbie

      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: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}"
                <rich:inplaceInput id="sand" defaultLabel="(add more)"
                     <a4j:support event="onviewactivated" action="#{cartMgr.cart.addEmail}" reRender="asn,sand"/>

      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.
        • 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.


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

            Manager Class:

            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.

            • 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}"/>

                And then in your stateful bean:

                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}" 
                       <f:param name="emailId" value="#{email.id}"/>

                  Then in my Java code for cart

                  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.


                  • 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.