You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Erik Weber <er...@mindspring.com> on 2004/07/17 07:30:20 UTC

Question on parameterizing action attribute to html:form

I want to use c:choose to decide how to set the value of the action 
parameter in an html:form tag (add or update).

How exactly do I refer to the variable that is set in the c:when and 
c:otherwise conditionals from within my html:action tag?

The only thing I can think of that works is something like this:

<html:form action="<%= someVar %>" . . . >

So how do I declare someVar, with c:set? Or do I have to use Scriptlet 
or JSP declaration syntax?

Erik


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


Re: Question on parameterizing action attribute to html:form

Posted by Rick Reumann <st...@reumann.net>.
Andrey Rogov wrote:

> there is another way to work with parameter form:action. If you use
> Tiles in your applications create one reusable tiles  lay with elements of
> design, control buttons and page control. In  this case you can use the page
> with many forms. Then solution <html:form action="${myFormBean.the_action_URI}"/>
> can be replaced with  <html:form action="${ControlBean.the_action_URI}"/> .
> 
> What do you think ?

Sure that could work (using Tiles or Sitemesh), but I'm not sure you 
gain that much by having a tile/include contain a header <htm:form 
action="${ControlBean.the_action_URI}"/> on it versus <html:form 
action="${myFormBean.the_action_URI}"/>. I probably wouldn't make a 
whole seperate tile just for the html:form header.

Most of the time I don't need to dynamically change the action name 
since the reusable form usually always has the same validation rules (an 
update versus and add for me usually has the same data on the page.. 
sometimes hidden though).  I also find it easier to understand when you 
can quickly look at the JSP and see the action name delcared in the form 
element.

Since I'm now leaning towards manually calling the validate methods 
anyway (to avoid those issues of having to repopulate lists when 
validation fails), I can always create custom validation calls based on 
whether I'm doing an update versus an insert if I need to. This why the 
Action name always remains the same on the form.

Obviously many ways to skin a cat here. I tend to avoid having dynamic 
action names since some time a year later someone will say "When I'm on 
such and such a page and click submit, I'm getting this wierd error." To 
track down the problem it's easy then to just look at the JSP and see 
the action it's submitting to. When it's dynamic it's a bit more of a 
pain to track down what is going on.

-- 
Rick

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


Re[2]: Question on parameterizing action attribute to html:form

Posted by Andrey Rogov <an...@ukrpost.net>.
Hi Rick,
there is another way to work with parameter form:action. If you use
Tiles in your applications create one reusable tiles  lay with elements of
design, control buttons and page control. In  this case you can use the page
with many forms. Then solution <html:form action="${myFormBean.the_action_URI}"/>
can be replaced with  <html:form action="${ControlBean.the_action_URI}"/> .

What do you think ?

( Your lessons still the best ).

Andrey .

RR> Erik Weber wrote:

>> if you have a single JSP 
>> that houses a form that is used for different commands (add, update), 
>> you are still going to need two separate form elements in 
>> validation.xml, causing redundancy (until "field inheritance" is 
>> implemented at least), correct?

RR> That is correct, although if you are using the "trick" way I mentioned 
RR> you could "sort" of get around this by setting up a 
RR> "baseEmployeeValidation" in your valiation.xml that you know will be 
RR> common amongst all the particular forms in question. Then you can create 
RR> a couple sub ones for the specifics (ie = "updateEmployeeValidation", 
RR> "insertEmployeeValiation"). Then, since you are calling the validation 
RR> manually you simply call the baseEmployeeValidation and then the 
RR> appropriate custom valiation in your action. I haven't tried this, but 
RR> it should work.

RR> Although I just took a brief look at the API and I'm not sure if you 
RR> call validate() more than once if you end up with a new Instance of the 
RR>   ValidationResults being set to the ValidationForm's instance of 
RR> "validatorResults." If it reuses the same instance and just adds on to 
RR> the map then that would be cool. If not, then the best you could do with 
RR> this trick would be to call the base common validation and if no errors 
RR> return then proceed on to validate the next custom validation. The 
RR> drawback to this is say the user completes a large form and submits. 
RR> It's possible he'll get a validation error saying "something is wrong" 
RR> and then he could submit after fixing it and get a new error (based on 
RR> the custom portion). Sort of annoying because it should come back all at 
RR> once. Anyway an attempt at this might look like:  (not tested at all)...

RR> validate(..) {
RR> ServletContext application = getServlet().getServletContext();
RR> ActionErrors errors = new ActionErrors();
RR> String parameter = request.getParameter( mapping.getParameter() );

RR> //set up Validator and test the base stuff common to both the add
RR> //update. Remember, we know the name of the base Validation..

RR> Validator validator = Resources.initValidator( "baseEmployeeValiation", 
RR> this, application, request, errors, page);
RR> try {
RR> validatorResults = validator.validate();
RR> } catch (ValidatorException e) {
RR> log.error(e.getMessage(), e);
RR> }

RR> //you might in the above also be able to test this custom
RR> //stuff, just haven't looked at how validator.validate() deals
RR> //with validatorResults if validate is called more than once

RR> //parameter would be your dispatch parameter represening the
RR> //"custom" unique part that needs validation..ie "addEmployee"
RR> //or "updateEmployee"

RR> if ( validatorResults.isEmpty() ) { //no errors from the base test
RR>   validator = Resources.initValidator( parameter, this, application,
RR>   request, errors, page);
RR>   try {
RR>    validatorResults = validator.validate();
RR>   } catch (ValidatorException e) {
RR>    log.error(e.getMessage(), e);
RR>   }
RR> }

RR>   return errors;
RR> }


RR> Probably easier just to delcare the two different validations in the xml 
RR> and copy and paste the common validations into both:) Extends sure would 
RR> be nice.




-- 
Best regards,
 Andrey                            mailto:andrey.rogov@ukrpost.net


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


Re: Question on parameterizing action attribute to html:form

Posted by Rick Reumann <st...@reumann.net>.
Erik Weber wrote:

> if you have a single JSP 
> that houses a form that is used for different commands (add, update), 
> you are still going to need two separate form elements in 
> validation.xml, causing redundancy (until "field inheritance" is 
> implemented at least), correct?

That is correct, although if you are using the "trick" way I mentioned 
you could "sort" of get around this by setting up a 
"baseEmployeeValidation" in your valiation.xml that you know will be 
common amongst all the particular forms in question. Then you can create 
a couple sub ones for the specifics (ie = "updateEmployeeValidation", 
"insertEmployeeValiation"). Then, since you are calling the validation 
manually you simply call the baseEmployeeValidation and then the 
appropriate custom valiation in your action. I haven't tried this, but 
it should work.

Although I just took a brief look at the API and I'm not sure if you 
call validate() more than once if you end up with a new Instance of the 
  ValidationResults being set to the ValidationForm's instance of 
"validatorResults." If it reuses the same instance and just adds on to 
the map then that would be cool. If not, then the best you could do with 
this trick would be to call the base common validation and if no errors 
return then proceed on to validate the next custom validation. The 
drawback to this is say the user completes a large form and submits. 
It's possible he'll get a validation error saying "something is wrong" 
and then he could submit after fixing it and get a new error (based on 
the custom portion). Sort of annoying because it should come back all at 
once. Anyway an attempt at this might look like:  (not tested at all)...

validate(..) {
ServletContext application = getServlet().getServletContext();
ActionErrors errors = new ActionErrors();
String parameter = request.getParameter( mapping.getParameter() );

//set up Validator and test the base stuff common to both the add
//update. Remember, we know the name of the base Validation..

Validator validator = Resources.initValidator( "baseEmployeeValiation", 
this, application, request, errors, page);
try {
validatorResults = validator.validate();
} catch (ValidatorException e) {
log.error(e.getMessage(), e);
}

//you might in the above also be able to test this custom
//stuff, just haven't looked at how validator.validate() deals
//with validatorResults if validate is called more than once

//parameter would be your dispatch parameter represening the
//"custom" unique part that needs validation..ie "addEmployee"
//or "updateEmployee"

if ( validatorResults.isEmpty() ) { //no errors from the base test
  validator = Resources.initValidator( parameter, this, application,
  request, errors, page);
  try {
   validatorResults = validator.validate();
  } catch (ValidatorException e) {
   log.error(e.getMessage(), e);
  }
}

  return errors;
}


Probably easier just to delcare the two different validations in the xml 
and copy and paste the common validations into both:) Extends sure would 
be nice.

-- 
Rick

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


Re: Question on parameterizing action attribute to html:form

Posted by Erik Weber <er...@mindspring.com>.
Rick, thank you for your thoughtfulness and generosity.

You made me realize that I can set the form action URI as a form bean 
attribute in my setup Action class, and then, instead of implementing a 
c:choose switch on a "command" request attribute in my JSP to set the 
form action URI, I can just use:

<html:form action="${myFormBean.the_action_URI}"/> as you suggested. 
Yes, I do need to parameterize this URI for the sake of the form 
validator plugin (as far as I know). But you have improved my code -- 
tentatively as I haven't actually gotten to this yet :-)

I am not using the MappingDispatchAction as I cannot go to 1.2 yet, but 
it will be easy to upgrade to it, as I am setting the "parameter" 
attribute in my action mappings in required fashion. But for now I am 
simply using an if-else construct that uses String.equals with this 
parameter to decide which "command" to execute in my Action class (it 
extends ValidatorAction).

Also, the "trick" you describe below to manually invoke the Validator 
plugin via a form bean's validate method is clever and useful indeed. I 
may try that, and definitely will in the case of multiple submit 
buttons. But still, even with this technique, if you have a single JSP 
that houses a form that is used for different commands (add, update), 
you are still going to need two separate form elements in 
validation.xml, causing redundancy (until "field inheritance" is 
implemented at least), correct?

Thanks again for your help,

Erik





Rick Reumann wrote:

> Erik Weber wrote:
>
>> I found the answer. It is to use the struts-el html tag library 
>> instead of the standard html tag library, and then to refer to the 
>> variable using the expression language syntx:
>>
>> <c:set var="action" value="/foo/update"/>
>>
>> . . .
>>
>> <html:form action="${action}" . . . />
>
>
> Erik are you uisng one of the DispatchActions (regular DispatchAction, 
> LookUpDipsatcchAction, in 1.2 MappingDispatchAction)? In these cases 
> you could reuse ONE mapping to accomplish your different common tasks 
> and won't need to change the form Action name.
>
> For example, say you were dealing with updating, inderting, viewing 
> Employee information. I would make one DispatchAction called 
> "EmployeeDispatchAction" and in there you'd you have your different 
> methods:
>
> update(..), retrieve(..), maybe even getListOfEmployees(..), etc.
>
> Then your form mapping would simply be something like 
> 'employeeAction', which would result in
>
> <html:form action="employeeAction"> <--- no need for dynamically 
> changing the action attribute
>
> What method gets called inisde of EmployeeDispatchAction is based on 
> the parameter you decide to use (I like to call mine "userAction"). So 
> if using the LookupDispatchAction I have a hidden variable which is 
> set to this variable:
>
> <html:hidden property="userAction"/>
>
> The nice thing is you also shouldn't need to do any logic on JSP 
> either for this, since you can set the "userAction" BEFORE you get to 
> the page in the Action you are coming from (always go through an 
> action:). So for example you click on a menu link called "update 
> employee" - before bringing you to the update employee page you'd 
> first go through a SetUp method in an action and since you know you 
> are then proceding on to the "update" page you simply set the form 
> variable...
>
> myForm.setUserAction(Constants.UPDATE) or
> myForm.setUserAction("update") or if DynaForm:
> myForm.set("userAction","update"); or use a Constants.UPDATE
>
> Now I think I remember an earlier discussion where different 
> validations (using the same form) were an issue. In that case having 
> separate action names could be helpful. But even there I'd key the 
> action value based of the parameter for your dispatch action name (no 
> need to do any set or loigic):
>
> <html:form action="${myFormBean.userAction}">
> ...
> </html:form>
>
>
> And another approach I've used before is a little awkward but it can 
> come in handy and your JSP would even avoid the el above. You'd have 
> one action name (ie action="employeeAction") and of course a dispatch 
> parameter on the page somewhere and which is defined in the action 
> mapping (ie parameter="userAction"). Then you can simply call your 
> form bean's validate method manually. Your formBean would have an 
> over-ridden validate method and it can call the appropriate validator 
> based on the dispatch parameter. It came in handy for a case where I 
> had different submit buttons on one form and depending on which one 
> was selected I had to validate differently. I found it pretty clean. 
> If you ever go this route here's an example...
>
> validation.xml:
>
> <form name="displayFromIndiIds">
> <field property="cardStartId"
> depends="required,integer">
> <arg0 key="gc.cardStartId.displayname"/>
> </field>
> ...
>
> FormBean with over-riden validate:
>
> validate(..) {
> ServletContext application = getServlet().getServletContext();
> ActionErrors errors = new ActionErrors();
> String parameter = request.getParameter( mapping.getParameter() );
> //parameter would be your dispatch parameter ie displayFromIndiIds
> Validator validator = Resources.initValidator( parameter, this, 
> application, request, errors, page);
> try {
> validatorResults = validator.validate();
> } catch (ValidatorException e) {
> log.error(e.getMessage(), e);
> }
> return errors;
> }
>
>
>
>
>
>
>

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


Re: Question on parameterizing action attribute to html:form

Posted by Rick Reumann <st...@reumann.net>.
Erik Weber wrote:

> I found the answer. It is to use the struts-el html tag library instead 
> of the standard html tag library, and then to refer to the variable 
> using the expression language syntx:
> 
> <c:set var="action" value="/foo/update"/>
> 
> . . .
> 
> <html:form action="${action}" . . . />

Erik are you uisng one of the DispatchActions (regular DispatchAction, 
LookUpDipsatcchAction, in 1.2 MappingDispatchAction)? In these cases you 
could reuse ONE mapping to accomplish your different common tasks and 
won't need to change the form Action name.

For example, say you were dealing with updating, inderting, viewing 
Employee information. I would make one DispatchAction called 
"EmployeeDispatchAction" and in there you'd you have your different methods:

update(..), retrieve(..), maybe even getListOfEmployees(..), etc.

Then your form mapping would simply be something like 'employeeAction', 
which would result in

<html:form action="employeeAction">  <--- no need for dynamically 
changing the action attribute

What method gets called inisde of EmployeeDispatchAction is based on the 
parameter you decide to use (I like to call mine "userAction"). So if 
using the LookupDispatchAction I have a hidden variable which is set to 
this variable:

<html:hidden property="userAction"/>

The nice thing is you also shouldn't need to do any logic on JSP either 
for this, since you can set the "userAction" BEFORE  you get to the page 
  in the Action you are coming from (always go through an action:). So 
for example you click on a menu link called "update employee" - before 
bringing you to the update employee page you'd first go through a SetUp 
method in an action and since you know you are then proceding on to the 
"update" page you simply set the form variable...

myForm.setUserAction(Constants.UPDATE) or
myForm.setUserAction("update") or if DynaForm:
myForm.set("userAction","update"); or use a Constants.UPDATE

Now I think I remember an earlier discussion where different validations 
(using the same form) were an issue. In that case having separate action 
names could be helpful. But even there I'd key the action value based of 
the parameter for your dispatch action name (no need to do any set or 
loigic):

<html:form action="${myFormBean.userAction}">
...
</html:form>


And another approach I've used before is a little awkward but it can 
come in handy and your JSP would even avoid the el above. You'd have one 
action name (ie action="employeeAction") and of course a dispatch 
parameter on the page somewhere and which is defined in the action 
mapping (ie parameter="userAction"). Then you can simply call your form 
bean's validate method manually. Your formBean would have an over-ridden 
validate method and it can call the appropriate validator based on the 
dispatch parameter. It came in handy for a case where I had different 
submit buttons on one form and depending on which one was selected I had 
to validate differently. I found it pretty clean.  If you ever go this 
route here's an example...

validation.xml:

<form name="displayFromIndiIds">
             <field property="cardStartId"
                 depends="required,integer">
                 <arg0 key="gc.cardStartId.displayname"/>
             </field>
...

FormBean with over-riden validate:

validate(..) {
   ServletContext application = getServlet().getServletContext();
   ActionErrors errors = new ActionErrors();
   String parameter = request.getParameter( mapping.getParameter() );
//parameter would be your dispatch parameter ie displayFromIndiIds
   Validator validator = Resources.initValidator( parameter, this, 
application, request,  errors, page);
   try {
             validatorResults = validator.validate();
         } catch (ValidatorException e) {
             log.error(e.getMessage(), e);
         }
  return errors;
}







-- 
Rick

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


Re: Question on parameterizing action attribute to html:form

Posted by Erik Weber <er...@mindspring.com>.
I found the answer. It is to use the struts-el html tag library instead 
of the standard html tag library, and then to refer to the variable 
using the expression language syntx:

<c:set var="action" value="/foo/update"/>

. . .

<html:form action="${action}" . . . />

Erik Weber wrote:

> I want to use c:choose to decide how to set the value of the action 
> parameter in an html:form tag (add or update).
>
> How exactly do I refer to the variable that is set in the c:when and 
> c:otherwise conditionals from within my html:action tag?
>
> The only thing I can think of that works is something like this:
>
> <html:form action="<%= someVar %>" . . . >
>
> So how do I declare someVar, with c:set? Or do I have to use Scriptlet 
> or JSP declaration syntax?
>
> Erik
>
>
> ---------------------------------------------------------------------
> 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