You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Jim Newsham <ne...@hotu.com> on 2001/03/08 21:07:26 UTC

Re: logic:iterate and form controls, revisited


Brian Knorr wrote:

> Jim,
>
> Hi... could you show me a small example of how you got this to work with
> the <html:text> tags... I can only get it to work with the way Eric Wu
> describes below.  Do you know if this will problem is going to be fixed
> anytime soon?  Thanks.
>
> --Brian
>
>                 I'll second this.  Using a recent version of struts, I
> have been able to use
>                 nested/indexed properties in the jsp page to put a
> variable number of fields in
>                 the form, without patching BeanUtils (points c and d).
> I still find it
>                 necessary to programmatically construct the field name
> (point b), but there is
>                 nothing stopping you from using the <html:text> tags
> (and others) (point a),
>                 which make things a little easier/cleaner since the tags
> will automatically
>                 populate your fields from the Form object.
>
>                 Jim Newsham
>
>                 Eric Wu wrote:
>
>                 > I have found that with the latest builds the support
> for nested and indexed
>                 > properties seem to eliminate the need to patch
> BeanUtils as described in
>                 > points c) and d) below.
>                 >
>                 > However, it seems that the <html:text> tag still
> cannot be used as it is not
>                 > able to generate the required indexed values for the
> name= and value=
>                 > parameters.  So you are left with coding the text
> fields using the HTML form
>                 > tags and scriptlets.  It is not the cleanest approach
> but at least with the
>                 > current builds, you don't need to worry about patching
> BeanUtils and
>                 > wondering if it will break the build...
>                 >
>                 > I agree that this should be given a fairly high
> priority for 1.1.
>                 >
>                 > Eric Wu
>                 > Java Architect
>                 > www.GlobalMedic.com
>                 > Tel.: 514.738.6770 / 1.888.986.3342
>                 > Fax.: 514.738.4827
>                 >
>                 > Silver WWW Health Awards Winner
>                 > Globe & Mail  Top 25 e-Businesses in Canada - #5
>                 > http://www.globetechnology.com/site/specials/e-25/
> <http://www.globetechnology.com/site/specials/e-25/>
>                 >
>                 > Visit www.medalliance.ca, GlobalMedic's new healthcare
> network for
>                 > physicians, pharmacists, patients and consumers,
> developed in collaboration
>                 > with Les Éditions Santé Rogers Media.
>                 >
>                 > -----Original Message-----
>                 > From: erikh@msoft.com [mailto:erikh@msoft.com
> <ma...@msoft.com> ]
>                 > Sent: January 24, 2001 2:50 AM
>                 > To: struts-user@jakarta.apache.org
>                 > Subject: logic:iterate and form controls, revisited
>                 >
>                 > Hi all,
>                 >
>                 > I recently ran in to a need to perform a task that's
> been discussed on
>                 > this list at least a couple of times since I've
> subscribed.
>                 > Unfortunately, an actual way to make it work was only
> described once,
>                 > and that approach was unappealing.
>                 >
>                 > The problem is that I would like to construct a JSP
> with an HTML FORM
>                 > that has a series of similar lines, using
> logic:iterate. The fundamental
>                 > problem is that the various struts-form tags use the
> same name for all
>                 > instances of a control in a given "column". This means
> that struts can't
>                 > automatically shove the posted data back into the form
> bean for you (at
>                 > least correctly!).
>                 >
>                 > The one approach to solving this that I saw (over the
> last two months
>                 > or so) was by Chandan Kulkarni. If you want to go back
> and check it
>                 > out, here are the headers:
>                 >
>                 > Date: Fri, 5 Jan 2001 07:44:11 -0500
>                 > To: <st...@jakarta.apache.org>, "Mishkin
> Berteig"
>                 > <mi...@berteig.com>
>                 > From: "Chandan Kulkarni" <ch...@expressotech.com>
>                 > Cc: "Chandan Kulkarni" <ch...@expressotech.com>
>                 > Subject: Re: Help: <logic:iterate> and form input
> fields
>                 > Message-ID:
> <002f01c07715$3520bb50$0100a8c0@ghar.expressotech.com
> <http://www.mail-archive.com/struts-user@jakarta.apache.org/msg01651.htm
> l> >
>                 >
>                 > This approach involves:
>                 >
>                 > (a) using raw HTML form tags, e.g., <input> instead of
> <form:text>.
>                 >
>                 > (b) constructing the value of the "name" and "value"
> attributes for the
>                 >     HTML form tags using JSP expression substitution -
> <%= %>.
>                 >
>                 > (c) Changing public static void populate(Object,
> String, String,
>                 >     HttpServletRequest) in BeanUtils.java to comment
> out the code which
>                 >     discards any subscript expression that might be
> present in the name
>                 >     part of a posted name/value pair.
>                 >
>                 > (d) Inserting code into public static void
> populate(Object, HashTable)
>                 >     in BeanUtils.java to look for an indexed or nested
> reference in the
>                 >     property name, and using PropertyUtils.setProperty
> to handle the
>                 >     setting in this case.
>                 >
>                 > Is there no way to accomplish this without all this
> monkey motion? I
>                 > would very much like to find a solution that doesn't
> require me to
>                 > modify code in struts.jar, and keep those changes up
> to date in the face
>                 > of future changes to struts. The fact that the code
> modified in (c)
>                 > *has* a check for a subscripted reference indicates to
> me that *someone*
>                 > was thinking along these lines in the past. Was the
> original intent to
>                 > do this in a different way? What am I breaking by
> commenting out this
>                 > code now?
>                 >
>                 > Better yet, does anyone have a *better* alternative?
> I'm not at all
>                 > averse to writing some tags to hide complexity at that
> point, or using a
>                 > derived ActionServlet class (I already am in fact, to
> load some
>                 > initialization parameters), but I'd really like to
> avoid modifying
>                 > struts itself!
>                 >
>                 > Am I being unreasonable? Are there really so few
> people out there that
>                 > want such an ability that no one has worked out a
> better way to do this?
>                 >
>                 > -- Erik

Hi Brian,

It's been a while since I've worked with struts as I've been put on other
projects, so if things have changed much with struts then I'm not quite up
to date.  Here's a snippet code that demonstrates the method I used.  It's
still necessary to use scriptlets to create the subscripted property names,
but the <html:text> tags take care of the subscripted variable lookup (that
was the point of my posting).

There's still a bit of dirty work to set up the nested objects, both
initially and when returning from a submitted form.  It's still not all
that pretty.  You need to make sure the nested object is built before the
jsp gets to it.  Then, you need to set up your form to reconstruct the
nested object when struts populates the form's parameters.

[this is somewhere within a <html:form>]
      <% for (int i = 0; i < form.getUsers(); i++) { %>
        <tr>
          <%-- the index is a just a handle; associate the index with a
user id --%>
          <html:hidden property='<%="user[" + i + "].userid"%>'/>

          <td>
            <%-- just a label --%>
            <bean:write name="editUserAgesForm"
                        property='<%="user[" + i + "].username"%>'/>
          </td>
          <td>
            <%-- user editable field --%>
            <html:text name="editUserAgesForm"
                        property='<%="user[" + i + "].age"%>'/>
          </td>

        </tr>
      <% } %>

For example, suppose there are 3 users with id's 9, 16, 18 named "Joe",
"Jack", "Nancy".  I set these up in the first Form object, so that
getUser(int index) returns the appropriate indexed User object (valid
indices are 0, 1, 2).  The user will see a form with 3 names and 3 spaces
to edit their ages.  Now, assume the user enters the ages "15", "16", "17"
in the form, for the three users.

In the receiving Form object, struts will try to call:
getUser(0).setUserid(9), getUser(1).setUserid(16),
getUser(0).setUserid(18), getUser(0).setAge("15"), getUser(1).setAge("16"),
getUser(2).setAge("17") -- BUT the order of these calls is arbitrary.  You
need to make sure the form does the right thing when calling getUser(n)
(probably create a new User object to temporarily hold the values; you
don't want to overwrite the real User objects until you've validated).

Notice in the above that I had to put the actual user id's in hidden fields
so that I could remember which indices correspond to which real users.

I hope this helps a little, I know it's pretty messy.  It will be nice when
struts does this sort of thing automatically.

Jim