Announcement Announcement Module
Collapse
No announcement yet.
Dynamic list binding Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Originally posted by abstraction
    Right now, I'm adding new objects as necessary in createBinder, though I'm not really happy with this solution.

    Can anyone post an example of using custom property editors to solve this problem? Any direction would be helpful.

    Here is the approach I have been using, it involves a custom editor. I don't know if it is optimal.. I am rather new to Spring Web.
    It requires the usage of some mutable List implementation (e.g. ArrayList).

    First, bind a custom editor (see below) for the list property. On value-to-text, this editor converts a list to it's size. On text-to-value, it will create a list of appropriate size, initialized with element instances.

    Secondly, embed the list property as a hidden input field on the form. At runtime this hidden field will contain the number of elements, so you should increment it when adding one client-side using JavaScript. Note that Spring uses a TreeMap when processing the request parameters, so the list property will be bound (and hence property initialized) before any of it's elements.

    This works for me, though it has not been thouroughly tested. I am curious to see if this works for others.


    (1) register editor


    Code:
    protected void initBinder(HttpServletRequest req, ServletRequestDataBinder binder) {
        binder.registerCustomEditor(List.class, "gateway.routingTable.entries", new ListSizeEditor<RoutingTableEntry>(RoutingTableEntry.class));
    }

    (2) sample jsp

    Code:
    <spring:bind path="routingTable.entries">
        <input type="hidden" name="${status.expression}" value="${status.displayValue}" />
    </spring:bind>
    ...
    <c:forEach items="${gatewayCreateCommand.gateway.routingTable.entries}" var="entry" varStatus="entryStatus">
        <spring:bind path="routingTable.entries[${entryStatus.index}].messageTypeFilter">
            <td><input type="text" name="${status.expression}" value="${status.displayValue}"/></td>
        </spring:bind>
        <spring:bind path="routingTable.entries[${entryStatus.index}].startsWithFilter">
            <td><input type="text" name="${status.expression}" value="${status.displayValue}"/></td>
        </spring:bind>
    </c:forEach>
    (3) custom editor

    Code:
    public class ListSizeEditor<T> extends
            PropertyEditorSupport {
        public static final int DEFAULT_MAX_SIZE = 1000;
    
        private final Class<T> element;
        private final int maxSize;
    
        public ListSizeEditor(Class<T> element) {
            this(element, DEFAULT_MAX_SIZE);
        }
    
        public ListSizeEditor(Class<T> element, int maxSize) {
            this.element = element;
            this.maxSize = maxSize;
        }
    
        public String getAsText() {
            return String.valueOf(getListValue().size());
        }
    
        public void setAsText(String text) throws
                IllegalArgumentException {
            List<T> value = getListValue();
            int size = Integer.parseInt(text);
            if (size > maxSize) {
                throw new RuntimeException("Maximum size exceeded.");
            }
            while (value.size() < size) {
                value.add(newInstance());
            }
            while (value.size() > size) {
                value.remove(value.size() - 1);
            }
            setValue(value);
        }
    
        private List<T> getListValue() {
            List<T> value = (List<T>) getValue();
            if (value == null) {
                throw new RuntimeException("This editor requires a not null value to be set, " +
                    "typically this could be an empty mutable list instead of null.");
            }
            return value;
        }
    
        private T newInstance() {
            try {
                return element.newInstance();
            }
            catch (InstantiationException e) {
                throw new RuntimeException(e);
            }
            catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }

    Comment


    • #17
      James,

      do you have the javascript code for adding the new row in the list?

      Thanks

      Comment

      Working...
      X