Wednesday, February 2, 2011

Struts2 vertical radio list without custom template

I have seen a lot of questions sent out into the void of the internet, wondering how you could do something as simple in Struts2 as make a radiobutton list display vertically instead of the default horizontally. The answer always seems to be writing a custom template for it. While this is an effective solution, it often does not fit the problem at hand.

I had an issue not long ago where I had to put a radio list inside of a grid, interspersed with other form elements. In this case, writing a custom template with <br> tags after each radio button did not work. So I came up with another way of handling this pesky situation. It is not quite as elegant as writing a custom template, but it will get the job done.

Basically, what you have to do to lay the radios out vertically is to use multiple radio tags, each pointing to the same selector variable, each with a limited version of the actual list. Here is a simple example:
<s:radio name="valueField" list="#{'value1':'label1'}"/><br>
<s:radio name="valueField" list="#{'value2':'label2'}"/><br>
<s:radio name="valueField" list="#{'value3':'label3'}"/>
That will display one radio button per line, still connected as a single list. It will default if "valueField" is already set, and it will successfully post back into "valueField".

As a bit meatier of an example, take the following code. This code shows an Action class with a List of Objects, which we will then iterate over in the jsp page. This shows a more typical setup.

ListObject.java:
public class ListObject {
    private String key;
    private String label;

    public ListObject(key,label) {
        this.key = key;
        this.label = label;
    }

    public String getKey() {
        return this.key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getLabel() {
        return this.label;
    }

    public void setLabel(String label) {
        this.label = label;
    }
}
ListAction.java
public class ListAction extends ActionSupport {
    private List<ListObject> myList;
    private String mySelection;
    
    public String input() {
        myList = new ArrayList<ListObject>();
        myList.add(new ListObject("val1","label1"));
        myList.add(new ListObject("val2","label2"));
        myList.add(new ListObject("val3","label3"));

        mySelection = "val2";

        return INPUT;
    }

    public String execute() {
        // Do stuff with list here
        return SUCCESS;
    }

    public List<ListObject> getMyList() {
        return myList;
    }
    public void setMyList(List<ListObject> newList) {
        this.myList = newList;
    }

    public String getMySelection() {
        return mySelection;
    }
    public void setMySelection(String newSelection) {
        this.mySelection = newSelection;
    }
}
list.jsp

    <s:radio theme="simple" name="mySelection" list="#{key:label}"/> <br>


At the core of this method is the specifying of independent sublists for each radio tag. The syntax inside the list attribute is the way you specify an in place list - "#{'key':'value','key2':'value2'}". For our lists, though, instead of using string literals, we are pulling the values from our iterator. Inside an iterator tag, the iterator object is at the top of the value stack, so that just referencing the variable names of the data members of the object pulls out the value successfully. Then Struts magic takes care of combining all those radio tags with the same name to point to the single back end data member.

Creating custom templates can often be the better solution, but in situations where that doesn't work, this is a good way to go as well.

No comments:

Post a Comment