Announcement Announcement Module
Collapse
No announcement yet.
_eventId_ with parameter? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • _eventId_ with parameter?

    Lets say I have a contact who has a list of addresses. I show the addresses underneath the contact with links to edit them. However, I want to retain any edits made to the contact as I go to edit the address.

    So, I can't use a href with flowExecutionId since that's not a submit. I can't use an _eventId_editAddress link because the eventId doesn't carry information on which address to edit.

    I ended up with a homegrown solution which used the format of '_eventIdWithParams_editAddress?param=value', but this was a while ago. What would be the best approach for this?

    Thanks,
    adam
    Last edited by adam_jh; Jan 22nd, 2010, 11:09 AM. Reason: clarity

  • #2
    Here's one way to do it:

    Code:
    <form:form ...>
    ...
    
       <c:forEach var="item" items="${addressesList}" varStatus="counter">
              ...render the list item row here...
    
             <%-- your image button (or you can just have a regular submit button) --%> 
             <input type="image" 
                     src="<c:url value="/resources/images/your_addr_edit_icon.png"/>"
                                name="_eventId_editAddress" 
                                value="${counter.count-1}"/>
    
       </c:forEach>
    </form:form ...>
    The form will be submitted with an additional request parameter. The name of the request parameter is, obviously, "_eventId_editAddress". As you know, that name will be parsed by SWF to extract the flow event ID (the part of the string after "_eventId_"). So the event ID recognized by SWF, is, naturally, "editAddress". Now, the parameter's value will be the index of the selected list element. That's what you want, right? (You can put anything you want there, anyway.) All field bindings on the form will also take place - if, you don't disable them in your state configuration. Note that in your view state configuration you will have to do something like this to capture the parameter value and, for example, place it into the flash scope, or other scope, or, perhaps, pass it to some action :

    Code:
    <view-state id="contactSummaryView" ... >
    ...
       <transition on="editAddress" to="addressEditView">
                <evaluate  expression="yourModel.getAddress(requestParameters._eventId_editAddress)" result="flashScope.addressToEdit" />
            </transition>
    You might want to transition to the same view, actually. In that case, just assign the selected address to some "currentlyEditedAddress" property on your form-backing bean in the "evaluate" expression on transition.

    Personally, I would like to see SWF provide a more elegant way of doing this, and, more importantly, allow adding to flow URLs more than one dynamic parameters that are "produced" by a click on a particular submit button - without JavaScript - and that can't or shouldn't be bound to form bean properties.) If SWF already parses the request parameters to extract the eventId, why not parse a bit further and allow a list of request params to follow after "&", just like in an ordinary URL string. Perhaps, there is a better way, and if there is I'd like to hear about it.

    HTH,
    Constantine
    Last edited by constv; Jan 22nd, 2010, 03:56 PM.

    Comment


    • #3
      Thanks a lot Constantine - that was the answer I was looking for, and you followed it through for me. Thanks again.

      In regards to adding additional parameters, I guess that is effectively what I had. I seem to remember being annoyed that everything had to be in the model object, but that was probably my initial misunderstanding of how to use webflow. I'm revisiting it now.

      To get additional parameters I created a copy of the org.springframework.webflow.mvc.servlet.FlowContro ller (because the flowHandlerAdapter is private) and added a line to the top of handleRequest method which created a custom wrapper of HttpServletRequest where I implemented the methods which can control the parameters of a query string - getQueryString, getParameter, getParameterMap, getParameterNames, getParameterValues. I used the _eventId_ and extracted params on its 'name' into real params. The rest of the methods deferred to the original request object. I seem to remember this was the easiest approach as there were too many classes to change and keep track of updates in webflow otherwise.

      adam
      Last edited by adam_jh; Jan 25th, 2010, 05:46 AM.

      Comment


      • #4
        still confused about _event_id and requestparameters

        Hi everyone,

        after reading this thread i still can figure it out

        What i want to do is the following:

        I have a html table with projects . And I want to create a link to go to view-state that shows the details for that specific project .

        <a href="${flowExecutionUrl}&_eventId_select &currentProjectId=${project.id}">${project.project Name}</a>

        If i correctly understood the previous posts currentProjectId will not be available in requestParameters of the new view state ? So maybe can somebody point me in the right direction to solve this problem ? Or am i looking at it the wrong way ? Any help will be greatly appriciated

        grts

        bert

        Comment


        • #5
          You are fine to do that as a href already has a parameter mechanism with the usual ?...& style. A form submit does not since its parameters are expected to list as separate '<input' elements. My issue was that the particular 'submit' element needed more parameters (well, just one extra one actually, the id - which can be sent in the value).

          Your request parameters will get absorbed into webflow's state mechanism and will no longer be available as a normal request parameters (webflow url's appear with parameters of ?e1s4) - so get them through webflow's requestParameters in your flows (http://static.springsource.org/sprin...e-requestScope)

          Comment


          • #6
            Constantine - It seems your original answer works in the case of an image, but it seems my workaround of multiple parameters on the 'name' input value is still required if you want to use the 'value' in some way - eg on a normal text input field the value is what is displayed to the user, which doesn't want to be an id number!

            Or have I missed something?

            Anybody else solve this?

            Comment


            • #7
              Originally posted by adam_jh View Post
              Constantine - It seems your original answer works in the case of an image, but it seems my workaround of multiple parameters on the 'name' input value is still required if you want to use the 'value' in some way - eg on a normal text input field the value is what is displayed to the user, which doesn't want to be an id number!
              That's correct, that's why I suggested an image button. Like I said, I wish SWF had a more flexible and generic solution. Using the "value" obviously is limited since there may only be one value. The only other way I see is to override the default SWF's URL parsing. Similar to what you have been doing, I guess. By default, on submit, SWF assumes that everything after "_eventId_" is the event ID string. I don't see why it could be parsed further to extract optional additional request parameters that may follow the eventId. This way, you could pass "_eventId_editAddress&selection_${varStatus.index} &something_${otherVal}" Your custom URL parser would extract "eventId", "selection", and "something" and place them into the request scope to be accessible via "requestParameters". I wonder why SWF does not allow for something like this...

              Comment


              • #8
                Thanks again.

                Seems there is a jira on this issue: http://jira.springframework.org/browse/SWF-1161

                Comment


                • #9
                  Originally posted by adam_jh View Post
                  Thanks again.

                  Seems there is a jira on this issue: http://jira.springframework.org/browse/SWF-1161
                  yeah, it's quite old and seems to have been ignored. Add your vote.

                  Comment


                  • #10
                    If i understand the problem correct, another way to solve this might be to create hidden fields (dynamically with javascript) when the Button is clicked. And then submit the form.

                    Though its not a 100% clean approach, it probably will work just fine.

                    Comment


                    • #11
                      yes, that approach would probably work. as you say though not 100% as without javascript the site doesn't function.

                      In case people want to improve on my method (please at least vote on the JIRA), I wrap the HttpServletRequest before it even reaches webflow. I guess I should have invested time in doing a patch for webflow...at the time I was sure I was doing something wrong - but turns out I was not.

                      Code:
                      package com.x.web;
                      
                      import java.io.BufferedReader;
                      import java.io.IOException;
                      import java.io.UnsupportedEncodingException;
                      import java.security.Principal;
                      import java.util.ArrayList;
                      import java.util.Collections;
                      import java.util.Enumeration;
                      import java.util.HashMap;
                      import java.util.Iterator;
                      import java.util.List;
                      import java.util.Locale;
                      import java.util.Map;
                      
                      import javax.servlet.RequestDispatcher;
                      import javax.servlet.ServletInputStream;
                      import javax.servlet.http.Cookie;
                      import javax.servlet.http.HttpServletRequest;
                      import javax.servlet.http.HttpSession;
                      
                      import org.apache.commons.lang.StringUtils;
                      import org.apache.commons.lang.text.StrBuilder;
                      import org.springframework.web.util.WebUtils;
                      
                      public class CustomHttpServletRequest implements HttpServletRequest {
                      
                      	HttpServletRequest request;
                      	public CustomHttpServletRequest(HttpServletRequest request) {
                      		this.request = request;
                      	}
                      
                      	public Map<String, String[]> getAdditionalParameters() {
                      		// only get those related to webflow
                      		Map origParams = WebUtils.getParametersStartingWith(request, "_eventIdWithParams_");
                      		Map newParams = new HashMap();
                      		if (!origParams.isEmpty()) {
                      			for (Iterator iterator = origParams.keySet().iterator(); iterator.hasNext();) {
                      				String name = (String) iterator.next();
                      				// we look for a parameter which includes a url-style query part to it in the input name
                      				// this only traps form submissions since they would already be split otherwise
                      				// so, see if there are any parameters within an input name
                      				String[] split = StringUtils.split(name, '?');
                      				if (split.length == 2) {
                      					// put the actual eventId transition in - it doesn't care for a value
                      					newParams.put("_eventId_" + split[0], new String[] {"dummy"});
                      					// split on '&'
                      					String[] parameters = StringUtils.split(split[1], '&');
                      					// include our extra parameters
                      					// NB we pay no attention to array style parameters - its one value per name
                      					for (int i = 0; i < parameters.length; i++) {
                      						String param = parameters[i];
                      						String[] extraParams = StringUtils.split(param, "=");
                      						String[] values = new String[]{extraParams[1]};
                      						newParams.put(extraParams[0], values);
                      					}
                      				}
                      			}
                      		}
                      		return newParams;
                      	}
                      
                      	/**/
                      	// methods related to getting parameters
                      	// TODO we should look at the efficiency of them
                      	public String getQueryString() {
                      		String query = request.getQueryString();
                      
                      		StrBuilder queryBuilder = new StrBuilder(query);
                      		Map<String, String[]> params = getAdditionalParameters();
                      		for (Iterator iterator = params.keySet().iterator(); iterator.hasNext();) {
                      			String param = (String) iterator.next();
                      			String[] values = params.get(param);
                      			if (!queryBuilder.isEmpty())
                      				queryBuilder.append("&");
                      			// we just take the first value and ignore the rest
                      			// TODO we should check how a normal request handles this
                      			queryBuilder.append(param + "=" + values[0]);
                      		}
                      		query = queryBuilder.toString();
                      		// stick to the api
                      		if (StringUtils.isEmpty(query))
                      			return null;
                      
                      		return query;
                      	}
                      	public String getParameter(String arg0) {
                      		String value = request.getParameter(arg0);
                      		// it appears this method expects a one off value
                      		if (value != null)
                      			return value;
                      		Map params = getAdditionalParameters();
                      		for (Iterator iterator = params.keySet().iterator(); iterator.hasNext();) {
                      			String name = (String) iterator.next();
                      			if (StringUtils.equals(arg0, name))
                      				return ((String[]) params.get(name))[0];
                      		}
                      		return null;
                      	}
                      	public Map getParameterMap() {
                      		Map map = request.getParameterMap();
                      		Map params = new HashMap<String, String[]>(map);
                      		params.putAll(getAdditionalParameters());
                      		return params;
                      	}
                      	public Enumeration getParameterNames() {
                      		Enumeration enumParams = request.getParameterNames();
                      		List<String> params = new ArrayList<String>();
                      		while (enumParams.hasMoreElements()) {
                      			String name = (String) enumParams.nextElement();
                      			params.add(name);
                      		}
                      		params.addAll(getAdditionalParameters().keySet());
                      		Enumeration enums = Collections.enumeration(params);
                      		return enums;
                      	}
                      	public String[] getParameterValues(String arg0) {
                      		String[] strings = request.getParameterValues(arg0);
                      		// we'll transfer to an expandable array, since we may add to it
                      		List<String> stringsList = new ArrayList<String>();
                      		if (strings != null) {
                      			for (int i = 0; i < strings.length; i++) {
                      				String str = strings[i];
                      				stringsList.add(str);
                      			}
                      		}
                      		Map<String, String[]> params = getAdditionalParameters();
                      		for (Iterator iterator = params.keySet().iterator(); iterator.hasNext();) {
                      			String name = (String) iterator.next();
                      			if (StringUtils.equals(arg0, name))
                      				for (int i = 0; i < params.get(name).length; i++)
                      					stringsList.add(params.get(name)[i]);
                      		}
                      		if (stringsList.isEmpty())
                      			return null;
                      		return stringsList.toArray(new String[0]);
                      	}
                      	/**/
                      
                      	public Object getAttribute(String arg0) {
                      		return request.getAttribute(arg0);
                      	}
                      	public Enumeration getAttributeNames() {
                      		return request.getAttributeNames();
                      	}
                      	public String getCharacterEncoding() {
                      		return request.getCharacterEncoding();
                      	}
                      	public int getContentLength() {
                      		return request.getContentLength();
                      	}
                      	public String getContentType() {
                      		return request.getContentType();
                      	}
                      	public ServletInputStream getInputStream() throws IOException {
                      		return request.getInputStream();
                      	}
                      	public String getLocalAddr() {
                      		return request.getLocalAddr();
                      	}
                      	public Locale getLocale() {
                      		return request.getLocale();
                      	}
                      	public Enumeration getLocales() {
                      		return request.getLocales();
                      	}
                      	public String getLocalName() {
                      		return request.getLocalName();
                      	}
                      	public int getLocalPort() {
                      		return request.getLocalPort();
                      	}
                      
                      
                      	public String getProtocol() {
                      		return request.getProtocol();
                      	}
                      	public BufferedReader getReader() throws IOException {
                      		return request.getReader();
                      	}
                      	public String getRealPath(String arg0) {
                      		return request.getRealPath(arg0);
                      	}
                      	public String getRemoteAddr() {
                      		return request.getRemoteAddr();
                      	}
                      	public String getRemoteHost() {
                      		return request.getRemoteHost();
                      	}
                      	public int getRemotePort() {
                      		return request.getRemotePort();
                      	}
                      	public RequestDispatcher getRequestDispatcher(String arg0) {
                      		return request.getRequestDispatcher(arg0);
                      	}
                      	public String getScheme() {
                      		return request.getScheme();
                      	}
                      	public String getServerName() {
                      		return request.getServerName();
                      	}
                      	public int getServerPort() {
                      		return request.getServerPort();
                      	}
                      	public boolean isSecure() {
                      		return request.isSecure();
                      	}
                      	public void removeAttribute(String arg0) {
                      		request.removeAttribute(arg0);
                      	}
                      	public void setAttribute(String arg0, Object arg1) {
                      		request.setAttribute(arg0, arg1);
                      	}
                      	public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException {
                      		request.setCharacterEncoding(arg0);
                      	}
                      	public String getAuthType() {
                      		return request.getAuthType();
                      	}
                      	public String getContextPath() {
                      		return request.getContextPath();
                      	}
                      	public Cookie[] getCookies() {
                      		return request.getCookies();
                      	}
                      	public long getDateHeader(String arg0) {
                      		return request.getDateHeader(arg0);
                      	}
                      	public String getHeader(String arg0) {
                      		return request.getHeader(arg0);
                      	}
                      	public Enumeration getHeaderNames() {
                      		return request.getHeaderNames();
                      	}
                      	public Enumeration getHeaders(String arg0) {
                      		return request.getHeaders(arg0);
                      	}
                      	public int getIntHeader(String arg0) {
                      		return request.getIntHeader(arg0);
                      	}
                      	public String getMethod() {
                      		return request.getMethod();
                      	}
                      	public String getPathInfo() {
                      		return request.getPathInfo();
                      	}
                      	public String getPathTranslated() {
                      		return request.getPathTranslated();
                      	}
                      	public String getRemoteUser() {
                      		return request.getRemoteUser();
                      	}
                      	public String getRequestedSessionId() {
                      		return request.getRequestedSessionId();
                      	}
                      	public String getRequestURI() {
                      		return request.getRequestURI();
                      	}
                      	public StringBuffer getRequestURL() {
                      		return request.getRequestURL();
                      	}
                      	public String getServletPath() {
                      		return request.getServletPath();
                      	}
                      	public HttpSession getSession() {
                      		return request.getSession();
                      	}
                      	public HttpSession getSession(boolean arg0) {
                      		return request.getSession(arg0);
                      	}
                      	public Principal getUserPrincipal() {
                      		return request.getUserPrincipal();
                      	}
                      	public boolean isRequestedSessionIdFromCookie() {
                      		return request.isRequestedSessionIdFromCookie();
                      	}
                      	public boolean isRequestedSessionIdFromUrl() {
                      		return request.isRequestedSessionIdFromUrl();
                      	}
                      	public boolean isRequestedSessionIdFromURL() {
                      		return request.isRequestedSessionIdFromURL();
                      	}
                      	public boolean isRequestedSessionIdValid() {
                      		return request.isRequestedSessionIdValid();
                      	}
                      	public boolean isUserInRole(String arg0) {
                      		return request.isUserInRole(arg0);
                      	}
                      
                      }

                      Comment


                      • #12
                        and we need to override handleRequest in WebFlowController but it has private fields, so we need to replace it:
                        Code:
                        package com.x.web;
                        /*
                         * Copyright 2004-2008 the original author or authors.
                         *
                         * Licensed under the Apache License, Version 2.0 (the "License");
                         * you may not use this file except in compliance with the License.
                         * You may obtain a copy of the License at
                         *
                         *      http://www.apache.org/licenses/LICENSE-2.0
                         *
                         * Unless required by applicable law or agreed to in writing, software
                         * distributed under the License is distributed on an "AS IS" BASIS,
                         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
                         * See the License for the specific language governing permissions and
                         * limitations under the License.
                         */
                        
                        import java.util.HashMap;
                        import java.util.Map;
                        
                        import javax.servlet.http.HttpServletRequest;
                        import javax.servlet.http.HttpServletResponse;
                        
                        import org.springframework.beans.BeansException;
                        import org.springframework.beans.factory.InitializingBean;
                        import org.springframework.context.ApplicationContext;
                        import org.springframework.context.ApplicationContextAware;
                        import org.springframework.js.ajax.AjaxHandler;
                        import org.springframework.web.servlet.ModelAndView;
                        import org.springframework.web.servlet.mvc.Controller;
                        import org.springframework.webflow.context.servlet.FlowUrlHandler;
                        import org.springframework.webflow.executor.FlowExecutor;
                        import org.springframework.webflow.mvc.servlet.AbstractFlowHandler;
                        import org.springframework.webflow.mvc.servlet.FlowHandler;
                        import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter;
                        
                        /**
                         * The adapter between the Spring MVC Controller layer and the Spring Web Flow engine. This controller allows Spring Web
                         * Flow to run embedded as a Controller within a DispatcherServlet, the key piece of the Spring Web MVC platform. It is
                         * expected a DispatcherServlet HandlerMapping will care for mapping all requests for flows to this controller for
                         * handling.
                         * 
                         * @author Keith Donald
                         */
                        
                        // NB we only needed to overwrite handleRequest, but need the whole class since private variables are referenced
                        // was org.springframework.webflow.mvc.servlet.FlowController
                        
                        public class CustomWebFlowController implements Controller, ApplicationContextAware, InitializingBean {
                        
                        	private FlowHandlerAdapter flowHandlerAdapter = new FlowHandlerAdapter();
                        
                        	private Map flowHandlers = new HashMap();
                        
                        	private boolean customFlowHandlerAdapterSet;
                        
                        	/**
                        	 * Creates a new flow controller.
                        	 * @see #setFlowExecutor(FlowExecutor)
                        	 * @see #setFlowUrlHandler(FlowUrlHandler)
                        	 * @see #setAjaxHandler(AjaxHandler)
                        	 * @see #setFlowHandlerAdapter(FlowHandlerAdapter)
                        	 * @see #afterPropertiesSet()
                        	 */
                        	public CustomWebFlowController() {
                        
                        	}
                        
                        	/**
                        	 * Returns the central service for executing flows. Required.
                        	 */
                        	public FlowExecutor getFlowExecutor() {
                        		return flowHandlerAdapter.getFlowExecutor();
                        	}
                        
                        	/**
                        	 * Sets the central service for executing flows. Required.
                        	 * @param flowExecutor
                        	 */
                        	public void setFlowExecutor(FlowExecutor flowExecutor) {
                        		flowHandlerAdapter.setFlowExecutor(flowExecutor);
                        	}
                        
                        	/**
                        	 * Returns the configured flow url handler.
                        	 */
                        	public FlowUrlHandler getFlowUrlHandler() {
                        		return flowHandlerAdapter.getFlowUrlHandler();
                        	}
                        
                        	/**
                        	 * Sets the configured flow url handler.
                        	 * @param urlHandler the flow url handler.
                        	 */
                        	public void setFlowUrlHandler(FlowUrlHandler urlHandler) {
                        		flowHandlerAdapter.setFlowUrlHandler(urlHandler);
                        	}
                        
                        	/**
                        	 * Returns the configured Ajax handler.
                        	 */
                        	public AjaxHandler getAjaxHandler() {
                        		return flowHandlerAdapter.getAjaxHandler();
                        	}
                        
                        	/**
                        	 * Sets the configured Ajax handler.
                        	 * @param ajaxHandler the ajax handler
                        	 */
                        	public void setAjaxHandler(AjaxHandler ajaxHandler) {
                        		flowHandlerAdapter.setAjaxHandler(ajaxHandler);
                        	}
                        
                        	/**
                        	 * Set whether redirects sent by this controller should be compatible with HTTP 1.0 clients.
                        	 * <p>
                        	 * By default, this will enforce a redirect HTTP status code of 302 by delegating to
                        	 * <code>HttpServletResponse.sendRedirect</code>. Setting this to false will send HTTP status code 303, which is
                        	 * the correct code for HTTP 1.1 clients, but not understood by HTTP 1.0 clients.
                        	 * <p>
                        	 * Many HTTP 1.1 clients treat 302 just like 303, not making any difference. However, some clients depend on 303
                        	 * when redirecting after a POST request; turn this flag off in such a scenario.
                        	 * @see javax.servlet.http.HttpServletResponse#sendRedirect
                        	 */
                        	public void setRedirectHttp10Compatible(boolean redirectHttp10Compatible) {
                        		flowHandlerAdapter.setRedirectHttp10Compatible(redirectHttp10Compatible);
                        	}
                        
                        	/**
                        	 * Sets the custom flow handles for managing the access to flows in a custom manner.
                        	 * @param flowHandlers the flow handler map
                        	 */
                        	public void setFlowHandlers(Map flowHandlers) {
                        		this.flowHandlers = flowHandlers;
                        	}
                        
                        	/**
                        	 * Registers a flow handler this controller should delegate to to customize the control logic associated with
                        	 * managing the execution of a specific flow.
                        	 * @param flowHandler the handler
                        	 */
                        	public void registerFlowHandler(FlowHandler flowHandler) {
                        		flowHandlers.put(flowHandler.getFlowId(), flowHandler);
                        	}
                        
                        	/**
                        	 * Returns the flow handler adapter which this Controller uses internally to carry out handler workflow.
                        	 */
                        	public FlowHandlerAdapter getFlowHandlerAdapter() {
                        		return flowHandlerAdapter;
                        	}
                        
                        	/**
                        	 * Sets the flow handler adapter which this Controller uses internally to carry out handler workflow. Call this
                        	 * instead of the convenience accesors to completely customize flow controller workflow.
                        	 * @param flowHandlerAdapter the flow handler adapter
                        	 */
                        	public void setFlowHandlerAdapter(FlowHandlerAdapter flowHandlerAdapter) {
                        		this.flowHandlerAdapter = flowHandlerAdapter;
                        		customFlowHandlerAdapterSet = true;
                        	}
                        
                        	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
                        		if (!customFlowHandlerAdapterSet) {
                        			flowHandlerAdapter.setApplicationContext(applicationContext);
                        		}
                        	}
                        
                        	public void afterPropertiesSet() throws Exception {
                        		if (!customFlowHandlerAdapterSet) {
                        			flowHandlerAdapter.afterPropertiesSet();
                        		}
                        	}
                        
                        	// subclassing hooks
                        
                        	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
                        		// NB wrap the request to manipulate our eventId
                        		CustomHttpServletRequest requestWrapper = new CustomHttpServletRequest(request);
                        		FlowHandler handler = getFlowHandler(requestWrapper);
                        		return flowHandlerAdapter.handle(requestWrapper, response, handler);
                        	}
                        
                        	// internal helpers
                        
                        	private FlowHandler getFlowHandler(HttpServletRequest request) {
                        		FlowUrlHandler urlHandler = flowHandlerAdapter.getFlowUrlHandler();
                        		String flowId = urlHandler.getFlowId(request);
                        		return getFlowHandler(flowId);
                        	}
                        
                        	private FlowHandler getFlowHandler(String flowId) {
                        		FlowHandler handler = (FlowHandler) flowHandlers.get(flowId);
                        		if (handler == null) {
                        			handler = new DefaultFlowHandler(flowId);
                        		}
                        		return handler;
                        	}
                        
                        	private static class DefaultFlowHandler extends AbstractFlowHandler {
                        		private final String flowId;
                        
                        		public DefaultFlowHandler(String flowId) {
                        			this.flowId = flowId;
                        		}
                        
                        		@Override
                        		public String getFlowId() {
                        			return flowId;
                        		}
                        	}
                        
                        }

                        Comment


                        • #13
                          Originally posted by afe View Post
                          If i understand the problem correct, another way to solve this might be to create hidden fields (dynamically with javascript) when the Button is clicked. And then submit the form.

                          Though its not a 100% clean approach, it probably will work just fine.
                          Yes, you can do something like this (w/jQuery, for example):

                          Code:
                          <script type="text/javascript" src="<c:url value="/resources/js/jquery-1.3.2.min.js" />"></script>
                          
                          ...
                          <input id="selection" type="hidden" name="selection" value=""/>
                          ...
                          
                          <%-- In your table, as you iterate through rows... --%>
                          <c:forEach var="address" items="${addressList}" varStatus="counter">
                             <tr onclick="$('#selection').val('${counter.index}');">
                                 <td>...</td>
                                 <td>...</td>
                                 <%--  action column with edit, delete, etc. buttons --%>
                                 <td>
                                     <input type="image" alt="${action_caption}"
                                             src="<c:url value="/resources/images/icons/edit.png"/>"
                                             name="_eventId_editAddress"/>
                                     ... other buttons 
                                 </td>
                                     
                               </tr>
                          </c:forEach>
                          BTW, the example I gave in the beginning of this thread with setting the value of the image submit control won't work in IE, because the value will be overwritten by the browser. It only works in "good" browsers like Firefox, Safari, etc. So, that is not a viable solution. I am not sure I like Adam's example, just too convoluted, and it is generally a bad idea to create your own "versions" of framework classes vs. overriding or injecting your custom functionality. Definitely, SWF should have built-in support for this in 3.x. Hope they are listening.
                          Last edited by constv; Mar 4th, 2010, 12:13 PM.

                          Comment

                          Working...
                          X