Combining Mapped properties with Indexed properties in Struts

前端 未结 1 1155
面向向阳花
面向向阳花 2020-12-22 02:04

I\'m trying to have a dynamic form and, depending on an attribute type, I would like to display a different input style (textfield, radio buttons, dropdown, checklist, ...).

相关标签:
1条回答
  • 2020-12-22 02:24

    I looked into this issue and found out what was happening. The problem is not with Struts but with BeanUtils (which Struts uses for populating the form with the request parameters).

    I managed to duplicate this by extracting a (test only) snippet of code from the framework:

    public class MyForm {
      // assume this is your Struts ActionForm
      public void setValue(String key, Object val) {
        System.out.println(key + "=" + val);
      }
    }
    
    public class Test {
      public static void main(String[] args) 
          throws IllegalAccessException, InvocationTargetException {
        MyForm s = new MyForm();
        Map<String, Object> properties = new HashMap<String, Object>();
        // Your request should be like yourActionUrl?value(foo)=1&value(foo)=2&value(foo)=3 
        // and Struts calls bean utils with something like:
        properties.put("value(foo)", new String[] {"1", "2", "3"});
        BeanUtils.populate(s, properties);
      }
    }
    

    When your run this you get printed one value only (just as you desrbibed):

    foo=1
    

    The thing is that BeanUtils considers this a mapped property and treats it as such, going for a scalar value for the key. Since your value is an array it just uses the first element:

    ...
    } else if (value instanceof String[]) {
      newValue = getConvertUtils().convert(((String[]) value)[0], type);
    ...
    

    What you can do is modify your JSP and ActionForm to treat the list of values separately. Example modified:

    public class MyForm {
      private Map<String, Object> map = new HashMap<String, Object>();
    
      public void setValue(String key, Object val) {
        map.put(key, val);
      }
    
      public void setPlainValue(String[] values) {
        // this is correctly called; now delegate to what you really wanted 
        setValue("foo", values);
      }
    }
    
    public class Test {
      public static void main(String[] args) 
          throws IllegalAccessException, InvocationTargetException {
        MyForm s = new MyForm();
        Map<String, Object> properties = new HashMap<String, Object>();
        // Notice the change to your URL..
        // yourActionUrl?plainValue=1&plainValue=2&plainValue=3
        properties.put("plainValue", new String[] {"1", "2", "3"});
        BeanUtils.populate(s, properties);
      }
    }
    

    The above means that you use

    <input type="..." name="value(foo)" ... />
    

    for all the single elements in your JSP, while for your checkboxes (extending it to multivalue elements in general) you use

    <input type="checkbox" name="plainValue" ... />
    

    and you delegate to the map once in your ActionForm.

    0 讨论(0)
提交回复
热议问题