Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

This HOWTO will describe the usage of HTML form buttons to invoke different behavior in actions.

Determine which button was pressed

Using different methods

The method attribute of the submit tag can be used to implement buttons that submit to different methodsThe trick is that the type conversion of the framework can be used to test which button was pressed in a simple way. When a button is pressed, a parameter is set in the framework with the name and value that are specified as the name and value attributes of your HTML button. The framework converts this automatically to boolean value if an appropriate property of the Action is found.

These boolean Properties can be tested to determine which button was pressed:

Code Block
languagexml
langxml

<form action="MyAction.action">
<input type="submit" name="buttonOnePressed  <s:submit method="save" value="First optionSave"/> 
<input type="submit" name="buttonTwoPressed  <s:submit method="delete" value="Alternative OptionDelete"/> 
</form>
Code Block
languagejava
langjava

public class MyAction extends Action {

    /**
     * Action implementation
     *
     * Sets the message according to which button was pressed.
     **/
    public String executesave() {
        if (buttonOnePressed) {
            message="You pressed the first button";
        } else if (buttonTwoPressed) {
            message="You pressed the second button";
        } else {
    message = "The save button was pressed";
        return ERROR;
        }
        return SUCCES;
    }

    // Input parameters
    private boolean buttonOnePressed=false;
    private boolean buttonTwoPressed=false;

    public voidString setButtonOnePresseddelete(boolean value) {
        this.buttonOnePressedmessage = value;
"The delete button was }pressed";


    public void setButtonTwoPressed(boolean value) {
        this.buttonTwoPressed = valuereturn SUCCES;
    }
 
    // Output parameters

    private String message;
    public String getMessage() {
        return message;
    }
}

*Note_: Do not use String properties with buttons and test for the value that's set. This will break as soon as the _value attribute of the HTML button changes! This is likely because the value attribute is used as the button text shown to the user.

Dynamic

...

Set of

...

Buttons

Consider a web page showing a shopping cart or similiar tabular data. Often there is a button belonging to each row, in case of the shopping cart a delete button to remove the item from the cart. The number of buttons is dynamic and the id that couples the button to an item cannot go to the value attribute because all buttons should read "delete".

Wiki MarkupThe solution is to __ name * the buttons like delete\[123\], delete\[594\], delete\[494\] where 123, 594 and 494 are e.g. the items' ids:are, for example, item ids.

Code Block
languagexml
langxml
Code Block

<form action="UpdateCart.action">
  <ww<s:iterate value="items">
    <ww<s:property value="name"> 
    <input type="submit" name="delete[<ww<s:property value='id'>]" value="delete" /> <br/>
  </wws:iterate>
</form>

Wiki MarkupWhen e.g. the button for the item with the property id == "27" is pressed, a parameter named _delete\[27\]_ and value "delete" is set in your action. The trick is to us declare your action's property "delete" property as _a java.util.Map_. Then, a key will exist for the button that was pressed:.

Code Block
languagejava
langjava

public void class UpdateCart implements Action {

    // mustMust be initialized to be usable as a Struts webwork2 input parameter.
    private Map delete = new HashMap(); 

    /** 
     * This is somewhat counter intuitive. But a property like "delete[OS:27]"
     *  that is set to "delete" by Struts webwork2 will be interpreted by the underlying    
     *  OGNL expression engine as "set the property 27 of the action's property
     *  "delete" to the value "delete". So we must provide a getter for this
     */ action. A setter is not needed.
     */
    public Map getDelete() {
        return delete;
    }

    public String execute() {
        for (Iterator i = delete.keySet().iterator(); i.hasNext(); ) {
            String id = (String) i.next();
            ...
            // do what ever you want
            ...
         }
         ...
    }
}

In this case it would not be necessary to iterate the whole keySet because it contains only one key but the same code can be use to handle sets of checkboxes if this is prefered later:

Code Block
languagexml
langxml

<form action="UpdateCart.action">
  <ww<s:iterateiterator value="items">
    <ww<s:property value="name"> 
    <input type="checkbox" name="delete[<ww<s:property value='item'/>]" value="delete"/> <br/>
  </wws:iterate>iterator>
  <input type="submit" name="updateCart" value="Update the cart"/>
</form>

The two implementations can even be combined two provide a quick "delete this item" button and a set of checkboxes for "mass updates". All with the above code, cool eh?