You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Craig McClanahan <cr...@apache.org> on 2006/03/09 17:55:35 UTC

Re: How to generate form controls dynamically

On 3/9/06, Rivka Shisman <ri...@nite.org.il> wrote:
>
> Hi friends,
>
>
>
> I need to dynamically build an input form that may contain various
> html:fields (i.e. html:text, html:select, html:radio etc).
>
> The type and name of the html:field will be determined at runtime (from
> DB table).
>
> How can I do it using Struts and JSP?


Basically, you can not do this sort of thing with the Struts HTML tags ...
but you could easily do it with JavaServer Faces components.  A quick
snapshot to give you the idea of how it works:

    HtmlForm form = ...; // Acquire a reference to the parent form component

    HtmlOutputLabel label1 = new HtmlOutputLabel(); // Label for username
field
    label1.setValue("Username:");

    HtmlInputText username = new HtmlInputText(); // Username field
    username.setId("username");

    HtmlOutputLabel label2 = new HtmlOutputLabel(); // Label for password
field
    label2.setValue("Password:");

    HtmlInputSecret password = new HtmlInputSecret(); // Password field
    password.setId("password");

    HtmlCommandButton submit = new HtmlCommandButton(); // Submit button
    submit.setId("logon");

    List children = form.getChildren();
    children.add(label1);
    children.add(username);
    children.add(label2);
    children.add(password);
    children.add(submit);

There's lots more you can do, but this gives the basic flavor of dynamically
creating component hierarchies.

Thanks
>
> Rivka


Craig

Re: How to generate form controls dynamically

Posted by "Frank W. Zammetti" <fz...@omnytex.com>.
While it is true you cannot do it with Stuts HTML tags, remember that 
those tags render plain HTML when all is said and done, as does JSF 
incidentally, and there is nothing to stop you from doing that yourself. 
  It's a pretty trivial exercise really.

Frank

Craig McClanahan wrote:
> On 3/9/06, Rivka Shisman <ri...@nite.org.il> wrote:
>> Hi friends,
>>
>>
>>
>> I need to dynamically build an input form that may contain various
>> html:fields (i.e. html:text, html:select, html:radio etc).
>>
>> The type and name of the html:field will be determined at runtime (from
>> DB table).
>>
>> How can I do it using Struts and JSP?
> 
> 
> Basically, you can not do this sort of thing with the Struts HTML tags ...
> but you could easily do it with JavaServer Faces components.  A quick
> snapshot to give you the idea of how it works:
> 
>     HtmlForm form = ...; // Acquire a reference to the parent form component
> 
>     HtmlOutputLabel label1 = new HtmlOutputLabel(); // Label for username
> field
>     label1.setValue("Username:");
> 
>     HtmlInputText username = new HtmlInputText(); // Username field
>     username.setId("username");
> 
>     HtmlOutputLabel label2 = new HtmlOutputLabel(); // Label for password
> field
>     label2.setValue("Password:");
> 
>     HtmlInputSecret password = new HtmlInputSecret(); // Password field
>     password.setId("password");
> 
>     HtmlCommandButton submit = new HtmlCommandButton(); // Submit button
>     submit.setId("logon");
> 
>     List children = form.getChildren();
>     children.add(label1);
>     children.add(username);
>     children.add(label2);
>     children.add(password);
>     children.add(submit);
> 
> There's lots more you can do, but this gives the basic flavor of dynamically
> creating component hierarchies.
> 
> Thanks
>> Rivka
> 
> 
> Craig
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: How to generate form controls dynamically

Posted by Craig McClanahan <cr...@apache.org>.
On 3/9/06, t.ziemer@dkfz-heidelberg.de <t....@dkfz-heidelberg.de> wrote:
>
> Hello Craig,
>
> thanks for your answer. The phase listener is the correct timepoint for
> the
> component creation, yet it will be executed repeatedly for each request so
> how
> can I avoid re-adding components to the view tree? Isn't there something
> like a
> servlet's init() method? Otherwise I'd still have to perform a check like
> findComponent() on each request which I do not really like.


The phase listener will only be invoked repeatedly if you ask for *all*
phases.  If you implement getPhaseId() like this;

    public PhaseId getPhaseId() {
        return PhaseId.RENDER_RESPONSE;
    }

you will only get notified at the beginning and end of Render Response.

NOTE - even if you *are* listening to all phases, you can distinguish them
by calling event.getPhaseId() to see which phase you are in.

Thanks,
> Tom


Craig


Quoting Craig McClanahan <cr...@apache.org>:
>
> > On 3/9/06, Tom Ziemer <t....@dkfz-heidelberg.de> wrote:
> > >
> > > Hi Craig,
> > >
> > > sorry, if this is totally OT, but I just posted a similar question in
> > > the sun forum: Where would you actually place the code you mentioned
> > > within a JSF component? I mean beginEncode() is called each time the
> > > page is requested so what can I do, if I only want to add a component
> > > once? I don't think that implementing NamingContainer and calling
> > > findComponent() is a really nice solution ...
> >
> >
> > I can point you at a real example, if you prefer :-).
> >
> > You know how most databases come with some sort of client application
> > that
> > lets you type in SELECT statements and then dynamically creates a table
> > (based on the column names returned by the query) to display the
> > responses?
> > I've got just such an example app (shale-sql-browser) in the Shale
> > nightly
> > builds[1].  Drop the war file onto your favorite servlet container, and
> > type
> > "select * from zip_codes" into the query field and submit the form.
> >
> > Although this particular example uses Shale's "prerender()" callback
> > method,
> > it is still easy to understand when you'd do this in terms of the
> > standard
> > JSF lifecycle:
> >
> > * RESTORE VIEW - JSF sees the incoming request and restores
> >   the previous component tree
> >
> > * APPLY REQUEST VALUES - JSF updates the local values of
> >   any input components, based on the request parameters.  In this
> >   case, it notices the values of the "query" parameter, which will
> >   contain the SELECT statement to execute.
> >
> > * PROCESS VALIDATIONS - JSF checks any validations.  None
> >   in this example.
> >
> > * UPDATE MODEL VALUES - JSF pushes values into the model.
> >   In this case, it pushes the local value of the "query" parameter
> >   into the "query" property of the backing bean (Query.java).
> >
> > * INVOKE APPLICATION - Grab the query string and actually
> >   execute it, creating a ResultSet.  Find the table component,
> >   and clear its old children.  Grab the ResultSetMetaData for
> >   the result set.  Dynamically construct child components for
> >   all of the database columns that were returned.
> >
> > * RENDER RESPONSE - Display the resulting component tree,
> >   which was partially created from the JSP page (it has an
> >   empty <h:table> component for the response data) and partially
> >   created by dynamic component creation.
> >
> > So, you'd typically operate on the input data during the action method
> > that
> > is called when the form is submitted, setting up the data to be used
> > later.
> > If you are going to redisplay the same page, you can also do the
> > component
> > creation at that point in time -- if you're navigating to a different
> > page,
> > you will need a phase listener listening for a "before render response"
> > event, because you need the second page's component tree to have been
> > created already.
> >
> > If you're doing that, though, just go ahead and use Shale and stick the
> > component creation into the prerender() method.  That way you won't have
> > to
> > worry about what the heck a "phase listener" is.
> >
> > Thanks,
> > > Tom
> >
> >
> > Craig
> >
> > [1] http://cvs.apache.org/builds/struts/nightly/struts-shale/
> >
> >
> > Craig McClanahan wrote:
> > > > On 3/9/06, Rivka Shisman <ri...@nite.org.il> wrote:
> > > >> Hi friends,
> > > >>
> > > >>
> > > >>
> > > >> I need to dynamically build an input form that may contain various
> > > >> html:fields (i.e. html:text, html:select, html:radio etc).
> > > >>
> > > >> The type and name of the html:field will be determined at runtime
> > (from
> > > >> DB table).
> > > >>
> > > >> How can I do it using Struts and JSP?
> > > >
> > > >
> > > > Basically, you can not do this sort of thing with the Struts HTML
> > tags
> > > ...
> > > > but you could easily do it with JavaServer Faces components.  A
> > quick
> > > > snapshot to give you the idea of how it works:
> > > >
> > > >     HtmlForm form = ...; // Acquire a reference to the parent form
> > > component
> > > >
> > > >     HtmlOutputLabel label1 = new HtmlOutputLabel(); // Label for
> > > username
> > > > field
> > > >     label1.setValue("Username:");
> > > >
> > > >     HtmlInputText username = new HtmlInputText(); // Username field
> > > >     username.setId("username");
> > > >
> > > >     HtmlOutputLabel label2 = new HtmlOutputLabel(); // Label for
> > > password
> > > > field
> > > >     label2.setValue("Password:");
> > > >
> > > >     HtmlInputSecret password = new HtmlInputSecret(); // Password
> > field
> > > >     password.setId("password");
> > > >
> > > >     HtmlCommandButton submit = new HtmlCommandButton(); // Submit
> > button
> > > >     submit.setId("logon");
> > > >
> > > >     List children = form.getChildren();
> > > >     children.add(label1);
> > > >     children.add(username);
> > > >     children.add(label2);
> > > >     children.add(password);
> > > >     children.add(submit);
> > > >
> > > > There's lots more you can do, but this gives the basic flavor of
> > > dynamically
> > > > creating component hierarchies.
> > > >
> > > > Thanks
> > > >> Rivka
> > > >
> > > >
> > > > Craig
> > > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> > > For additional commands, e-mail: user-help@struts.apache.org
> > >
> > >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>

Re: How to generate form controls dynamically

Posted by t....@dkfz-heidelberg.de.
Hello Craig,

thanks for your answer. The phase listener is the correct timepoint for the
component creation, yet it will be executed repeatedly for each request so how
can I avoid re-adding components to the view tree? Isn't there something like a
servlet's init() method? Otherwise I'd still have to perform a check like
findComponent() on each request which I do not really like.

Thanks,
Tom

Quoting Craig McClanahan <cr...@apache.org>:

> On 3/9/06, Tom Ziemer <t....@dkfz-heidelberg.de> wrote:
> >
> > Hi Craig,
> >
> > sorry, if this is totally OT, but I just posted a similar question in
> > the sun forum: Where would you actually place the code you mentioned
> > within a JSF component? I mean beginEncode() is called each time the
> > page is requested so what can I do, if I only want to add a component
> > once? I don't think that implementing NamingContainer and calling
> > findComponent() is a really nice solution ...
> 
> 
> I can point you at a real example, if you prefer :-).
> 
> You know how most databases come with some sort of client application
> that
> lets you type in SELECT statements and then dynamically creates a table
> (based on the column names returned by the query) to display the
> responses?
> I've got just such an example app (shale-sql-browser) in the Shale
> nightly
> builds[1].  Drop the war file onto your favorite servlet container, and
> type
> "select * from zip_codes" into the query field and submit the form.
> 
> Although this particular example uses Shale's "prerender()" callback
> method,
> it is still easy to understand when you'd do this in terms of the
> standard
> JSF lifecycle:
> 
> * RESTORE VIEW - JSF sees the incoming request and restores
>   the previous component tree
> 
> * APPLY REQUEST VALUES - JSF updates the local values of
>   any input components, based on the request parameters.  In this
>   case, it notices the values of the "query" parameter, which will
>   contain the SELECT statement to execute.
> 
> * PROCESS VALIDATIONS - JSF checks any validations.  None
>   in this example.
> 
> * UPDATE MODEL VALUES - JSF pushes values into the model.
>   In this case, it pushes the local value of the "query" parameter
>   into the "query" property of the backing bean (Query.java).
> 
> * INVOKE APPLICATION - Grab the query string and actually
>   execute it, creating a ResultSet.  Find the table component,
>   and clear its old children.  Grab the ResultSetMetaData for
>   the result set.  Dynamically construct child components for
>   all of the database columns that were returned.
> 
> * RENDER RESPONSE - Display the resulting component tree,
>   which was partially created from the JSP page (it has an
>   empty <h:table> component for the response data) and partially
>   created by dynamic component creation.
> 
> So, you'd typically operate on the input data during the action method
> that
> is called when the form is submitted, setting up the data to be used
> later.
> If you are going to redisplay the same page, you can also do the
> component
> creation at that point in time -- if you're navigating to a different
> page,
> you will need a phase listener listening for a "before render response"
> event, because you need the second page's component tree to have been
> created already.
> 
> If you're doing that, though, just go ahead and use Shale and stick the
> component creation into the prerender() method.  That way you won't have
> to
> worry about what the heck a "phase listener" is.
> 
> Thanks,
> > Tom
> 
> 
> Craig
> 
> [1] http://cvs.apache.org/builds/struts/nightly/struts-shale/
> 
> 
> Craig McClanahan wrote:
> > > On 3/9/06, Rivka Shisman <ri...@nite.org.il> wrote:
> > >> Hi friends,
> > >>
> > >>
> > >>
> > >> I need to dynamically build an input form that may contain various
> > >> html:fields (i.e. html:text, html:select, html:radio etc).
> > >>
> > >> The type and name of the html:field will be determined at runtime
> (from
> > >> DB table).
> > >>
> > >> How can I do it using Struts and JSP?
> > >
> > >
> > > Basically, you can not do this sort of thing with the Struts HTML
> tags
> > ...
> > > but you could easily do it with JavaServer Faces components.  A
> quick
> > > snapshot to give you the idea of how it works:
> > >
> > >     HtmlForm form = ...; // Acquire a reference to the parent form
> > component
> > >
> > >     HtmlOutputLabel label1 = new HtmlOutputLabel(); // Label for
> > username
> > > field
> > >     label1.setValue("Username:");
> > >
> > >     HtmlInputText username = new HtmlInputText(); // Username field
> > >     username.setId("username");
> > >
> > >     HtmlOutputLabel label2 = new HtmlOutputLabel(); // Label for
> > password
> > > field
> > >     label2.setValue("Password:");
> > >
> > >     HtmlInputSecret password = new HtmlInputSecret(); // Password
> field
> > >     password.setId("password");
> > >
> > >     HtmlCommandButton submit = new HtmlCommandButton(); // Submit
> button
> > >     submit.setId("logon");
> > >
> > >     List children = form.getChildren();
> > >     children.add(label1);
> > >     children.add(username);
> > >     children.add(label2);
> > >     children.add(password);
> > >     children.add(submit);
> > >
> > > There's lots more you can do, but this gives the basic flavor of
> > dynamically
> > > creating component hierarchies.
> > >
> > > Thanks
> > >> Rivka
> > >
> > >
> > > Craig
> > >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> > For additional commands, e-mail: user-help@struts.apache.org
> >
> >
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: How to generate form controls dynamically

Posted by Craig McClanahan <cr...@apache.org>.
On 3/9/06, Tom Ziemer <t....@dkfz-heidelberg.de> wrote:
>
> Hi Craig,
>
> sorry, if this is totally OT, but I just posted a similar question in
> the sun forum: Where would you actually place the code you mentioned
> within a JSF component? I mean beginEncode() is called each time the
> page is requested so what can I do, if I only want to add a component
> once? I don't think that implementing NamingContainer and calling
> findComponent() is a really nice solution ...


I can point you at a real example, if you prefer :-).

You know how most databases come with some sort of client application that
lets you type in SELECT statements and then dynamically creates a table
(based on the column names returned by the query) to display the responses?
I've got just such an example app (shale-sql-browser) in the Shale nightly
builds[1].  Drop the war file onto your favorite servlet container, and type
"select * from zip_codes" into the query field and submit the form.

Although this particular example uses Shale's "prerender()" callback method,
it is still easy to understand when you'd do this in terms of the standard
JSF lifecycle:

* RESTORE VIEW - JSF sees the incoming request and restores
  the previous component tree

* APPLY REQUEST VALUES - JSF updates the local values of
  any input components, based on the request parameters.  In this
  case, it notices the values of the "query" parameter, which will
  contain the SELECT statement to execute.

* PROCESS VALIDATIONS - JSF checks any validations.  None
  in this example.

* UPDATE MODEL VALUES - JSF pushes values into the model.
  In this case, it pushes the local value of the "query" parameter
  into the "query" property of the backing bean (Query.java).

* INVOKE APPLICATION - Grab the query string and actually
  execute it, creating a ResultSet.  Find the table component,
  and clear its old children.  Grab the ResultSetMetaData for
  the result set.  Dynamically construct child components for
  all of the database columns that were returned.

* RENDER RESPONSE - Display the resulting component tree,
  which was partially created from the JSP page (it has an
  empty <h:table> component for the response data) and partially
  created by dynamic component creation.

So, you'd typically operate on the input data during the action method that
is called when the form is submitted, setting up the data to be used later.
If you are going to redisplay the same page, you can also do the component
creation at that point in time -- if you're navigating to a different page,
you will need a phase listener listening for a "before render response"
event, because you need the second page's component tree to have been
created already.

If you're doing that, though, just go ahead and use Shale and stick the
component creation into the prerender() method.  That way you won't have to
worry about what the heck a "phase listener" is.

Thanks,
> Tom


Craig

[1] http://cvs.apache.org/builds/struts/nightly/struts-shale/


Craig McClanahan wrote:
> > On 3/9/06, Rivka Shisman <ri...@nite.org.il> wrote:
> >> Hi friends,
> >>
> >>
> >>
> >> I need to dynamically build an input form that may contain various
> >> html:fields (i.e. html:text, html:select, html:radio etc).
> >>
> >> The type and name of the html:field will be determined at runtime (from
> >> DB table).
> >>
> >> How can I do it using Struts and JSP?
> >
> >
> > Basically, you can not do this sort of thing with the Struts HTML tags
> ...
> > but you could easily do it with JavaServer Faces components.  A quick
> > snapshot to give you the idea of how it works:
> >
> >     HtmlForm form = ...; // Acquire a reference to the parent form
> component
> >
> >     HtmlOutputLabel label1 = new HtmlOutputLabel(); // Label for
> username
> > field
> >     label1.setValue("Username:");
> >
> >     HtmlInputText username = new HtmlInputText(); // Username field
> >     username.setId("username");
> >
> >     HtmlOutputLabel label2 = new HtmlOutputLabel(); // Label for
> password
> > field
> >     label2.setValue("Password:");
> >
> >     HtmlInputSecret password = new HtmlInputSecret(); // Password field
> >     password.setId("password");
> >
> >     HtmlCommandButton submit = new HtmlCommandButton(); // Submit button
> >     submit.setId("logon");
> >
> >     List children = form.getChildren();
> >     children.add(label1);
> >     children.add(username);
> >     children.add(label2);
> >     children.add(password);
> >     children.add(submit);
> >
> > There's lots more you can do, but this gives the basic flavor of
> dynamically
> > creating component hierarchies.
> >
> > Thanks
> >> Rivka
> >
> >
> > Craig
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>

Re: How to generate form controls dynamically

Posted by Tom Ziemer <t....@dkfz-heidelberg.de>.
Hi Craig,

sorry, if this is totally OT, but I just posted a similar question in
the sun forum: Where would you actually place the code you mentioned
within a JSF component? I mean beginEncode() is called each time the
page is requested so what can I do, if I only want to add a component
once? I don't think that implementing NamingContainer and calling
findComponent() is a really nice solution ...

Thanks,
Tom

Craig McClanahan wrote:
> On 3/9/06, Rivka Shisman <ri...@nite.org.il> wrote:
>> Hi friends,
>>
>>
>>
>> I need to dynamically build an input form that may contain various
>> html:fields (i.e. html:text, html:select, html:radio etc).
>>
>> The type and name of the html:field will be determined at runtime (from
>> DB table).
>>
>> How can I do it using Struts and JSP?
> 
> 
> Basically, you can not do this sort of thing with the Struts HTML tags ...
> but you could easily do it with JavaServer Faces components.  A quick
> snapshot to give you the idea of how it works:
> 
>     HtmlForm form = ...; // Acquire a reference to the parent form component
> 
>     HtmlOutputLabel label1 = new HtmlOutputLabel(); // Label for username
> field
>     label1.setValue("Username:");
> 
>     HtmlInputText username = new HtmlInputText(); // Username field
>     username.setId("username");
> 
>     HtmlOutputLabel label2 = new HtmlOutputLabel(); // Label for password
> field
>     label2.setValue("Password:");
> 
>     HtmlInputSecret password = new HtmlInputSecret(); // Password field
>     password.setId("password");
> 
>     HtmlCommandButton submit = new HtmlCommandButton(); // Submit button
>     submit.setId("logon");
> 
>     List children = form.getChildren();
>     children.add(label1);
>     children.add(username);
>     children.add(label2);
>     children.add(password);
>     children.add(submit);
> 
> There's lots more you can do, but this gives the basic flavor of dynamically
> creating component hierarchies.
> 
> Thanks
>> Rivka
> 
> 
> Craig
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org