Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use multiple forms / actions in a single view in Struts 2

I have a search box which is displayed on every page. The JSP code for the search box is inserted into every page via tiles.

The search box has a form and an action class SearchAction which needs to preload some properties for drop down boxes. The SearchAction class has an input() method, which does this initialization.

Some pages also have their own form in the main area. Also with their own action class. They also have an input() method which does some preloading.

  1. Is it possible to use two actions in the same view?
  2. How can each form have access to it's own actions's properties.
  3. And how could I manage to have the input method of both action classes be called before the JSP is rendered?

Update:

I am adding a trimmed down example, since it's probably not clear what I am trying to do. It's a register page register.jsp with an RegisterAction. And the page also contains the search form. (BTW: I left out the getter/setter and other stuff in the action classes to keep it short):

register.jsp:

<s:form action="executeSearch">
    <s:textfield key="name" label="Name"/>
    <s:textfield key="age"  label="Age"/>
    <s:submit/>
</s:form>

<s:form action="executeRegister">
    <s:textfield key="firstName" label="First Name"/>
    <s:textfield key="lastName" label="Last Name"/>
    <s:textfield key="age" label="Age"/>
    <s:submit/>
</s:form>

struts.xml:

<action name="*Search" class="action.SearchAction" method="{1}">
    <result name="success">/searchresult.jsp</result>
</action>

<action name="*Register" class="action.RegisterAction" method="{1}">
    <result name="input">/register.jsp</result>
    <result name="success">/registerOk.jsp</result>
</action>

SearchAction.java:

public class SearchAction extends ActionSupport {

    private String name;
    private int age;

    @Override
    public String input() throws Exception {
        // preload the search form with some demo data
        name = "test";
        age = 20;
        return INPUT;
    }

    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }
    
    ...
}

RegisterAction.java:

public class RegisterAction extends ActionSupport {

    private String firstName;
    private String lastName;
    private int age;

    @Override
    public String input() throws Exception {
        // preload the register form with some demo data
        firstName = "John";
        lastName = "Rambo";
        age = 10;
        return INPUT;
    }

    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }
    
    ...
}

Let's say I call the action inputRegister.action. Then RegisterAction.input() is called. The properties are set. And result SUCCESS causes register.jsp to be rendered.

But what about my search form. How do I get access to the search action and it's model. Neither of those are on the ValueStack of course. And neither do I see a way to call any methods of SearchAction in order to initialize it's model. I deliberately choose age to be in both action classes. In the rendered page you can see that the search form also accesses the RegisterAction-*.properties (because that's on top of the ValueStack). But it needs to access SearchAction. It must display 20 and not 10.

Rendered Jsp Page

I am clearly doing it wrong. But even after a lot of googling, I still did't find out the right way to do it.

like image 501
nharrer Avatar asked Oct 31 '22 23:10

nharrer


2 Answers

As I found (please correct me): Two forms need to be initiated in their own actions before be show to user, when you ask for Registration form, the search form does not get initiated, as its action is never called.

This is a common problem which can be easily handled with Ajax, DO NOT LOAD ALL YOUR PAGE DATA. Please have a look at http://struts.jgeppert.com/struts2-jquery-showcase/index.action. There is a Theme selection select box, which has been initiated once. Loading other part of the page, will be done via Ajax and thus the theme selection, action which initiates the select box, does not need to be re-run. You can easily use the struts 2 jquery plugin to achieve it.

If you can not use Ajax (with any reason), then there is no simple way. You should manually initiate the you search form items, in EACH action, to make sure that your struts tag can read search form initiated data. You can think of it as you need to some how, cut and paste the body of your search action in all your actions !!

like image 171
Alireza Fattahi Avatar answered Nov 15 '22 04:11

Alireza Fattahi


The concept of the view is used to perform any number of actions, and any action can have any number of results. A result is used to return a view. The action that returns a view is placed on top of the ValueStack to be easy accessible via evaluating OGNL expressions. The result view could be mapped to any action in any action class. It knows nothing about action which calls it, but it can determine it, again using OGNL. You can map actions to different method of the same action class, so you don't need to have many input() methods.

EDIT:

You problem is you bounded form fields wrong. Each form should have a separate storage to display it correctly. Fields are bounded by name, and you'd better have a form bean for the search condition variables and put it somewhere in the action context.

<s:form action="executeSearch">
    <s:textfield key="searchBean.name" label="Name"/>
    <s:textfield key="searchbean.age"  label="Age"/>
    <s:submit/>
</s:form>

<s:form action="executeRegister">
    <s:textfield key="firstName" label="First Name"/>
    <s:textfield key="lastName" label="Last Name"/>
    <s:textfield key="age" label="Age"/>
    <s:submit/>
</s:form> 

Note: the key attribute generates name, label, and value.

Each action needs to initialize a searchBean, unless it has a session scope. If you put a bean to a session, then you should use #session. prefix. More about OGNL you can find on the docs page.

like image 25
Roman C Avatar answered Nov 15 '22 05:11

Roman C