Announcement Announcement Module
Collapse
No announcement yet.
Multiple forms on one view? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Multiple forms on one view?

    How do you go about setting up multiple HTML forms on the same view? For example, I would like to have a template that is used to build every view on my site, and which includes sections for a header, a work area, and a footer. In the header, I would like to have a "Product Lookup" form that is always available. There may or may not be another HTML form in the work area section at any given time. I'm not even sure where to begin trying to figure out how to set this up. Hope that was clear.

    Thanks!
    Brian

  • #2
    We do something similar, it's not a problem. You can have different bits - headers, footers, forms, whatever - included in your views with include lines.
    The form action will send the form parameters to the appropriate controller to handle it.
    The only thing to be aware of is that if the form uses <spring:bind> tags to display errors etc., you have to have the formbacking object with the errors instance in the model, otherwise you get an error.
    So you may need two versions of your form jsp: one without the spring bind tags, just for entry, which can be used in any view; and one with the error display handling which is used by the controller that handels the form's input.
    Unless there is a better way of handling this issue?

    Comment


    • #3
      Sorry, Chris, I'm just getting started with Spring MVC, and I'm still not clear how to configure a single view to support multiple form controllers.

      From my springapp-servlet.xml:

      Code:
      <bean id="form1Controller" class="Form1Controller">
          <property name="sessionForm"><value>true</value></property>
          <property name="commandName"><value>Form1Command</value></property>
          <property name="validator"><ref bean="form1Validator"/></property> 
          <property name="formView"><value>myOnlyView</value></property>
          <property name="successView"><value>form1Confirmation</value></property>
      </bean>
      
      <bean id="form2Controller" class="Form2Controller">
          <property name="sessionForm"><value>true</value></property>
          <property name="commandName"><value>Form2Command</value></property>
          <property name="validator"><ref bean="form2Validator"/></property>
          <property name="formView"><value>myOnlyView</value></property>
          <property name="successView"><value>form2Confirmation</value></property>
      </bean>
      
      <bean id="form1Validator" class="Form1Validator"/>
      
      <bean id="form2Validator" class="Form2Validator"/>
      
      <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
          <property name="mappings">
              <props>
                  <prop key="/myOnlyView.vm">form1Controller</prop>
              </props>
          </property>
      </bean>
      Obviously a couple of issues with this. The primary issue is that the url "/myOnlyView.vm" can only be mapped to one of the two form controllers. The other form controller is never activated ("activated" probably isn't the correct term here... but it doens't work, anyways, and from a lack of log messages it is never "activated").

      Here is an example of the HTML that I would like to be able to somehow link up to one or more form controllers:

      Code:
      <html>
      <head></head>
      <body>
      <form id="form1" action="get">
      ...
      </form>
      <form id="form2" action="get">
      ...
      </form>
      </body>
      </html>
      Hope that's clear. Thanks in advance.

      Brian

      Comment


      • #4
        Hello,

        There are many issues concerning multiple form submission. I understand, that you would also like to invoke many controllers during submission. I had similar problem so I had to develop simple chaining mechanism based on the Chain of Responsibility pattern.

        If you problem concerns multiple form submission at single request I could give you more details.

        Comment


        • #5
          I'm actually trying to support two forms on one view, each with an independent form controller and independent form submission. I'm not trying to submit more than one form at once. Sorry if that was unclear.

          For an example of what I'm talking about, see www.amazon.com. On the left side of their home page are two search forms, one which allows you to search Amazon's "inventory", and another which allows you to do a "web search". Both are written as independent HTML forms. Both have a little, round, orange or red "GO!" button next to them.

          Thanks again.

          Brian

          Comment


          • #6
            If I understand what you want to do is:
            • Have one display page.
            • Have two (or more) forms with different processing logic.
            • Display the processing results in the 'same' view/URL for all forms.

            This is one of the things that, while no worse that others, Spring doesn't really help too much with. What I've often done is set up 3 controllers:

            Code:
            <bean id="form1Controller" class="Form1Controller">...</bean>
            <bean id="form2Controller" class="Form2Controller">...</bean> 
            <bean id="displayController" class="DisplayController">...</bean>
            Then the processing controllers can send redirects to the URL mapped to the displayController. If you don't mind having different URLs, then you can do without the displayController.

            Also note that if a form doesn't have an action="x" then it submits to the current URL, so for multiple forms only 1 can submit to the current page:
            Code:
            <form id="form1" method="get">
            ...
            </form>
            <form id="form2" method="get" action="MyFormController2URL">
            ...
            </form>
            Also, take a look at the ParameterizableViewController class in the mvc package, depending on how much processing per-form, etc.. it may also suit your needs.

            Comment


            • #7
              Brian,

              You've had a number of answers so far, so if you're sorted now, fine.
              But if not, my understanding is you want two (or more) forms on one page, say a product query form, and a login form. If they complete and submit the product query form, they get back a search results page. If they complete and submit the login form, they get a page saying they've successfully logged in (or not), and maybe showing their details. Or whatever.

              So in the jsp of the view with multiple forms, you need, for example:

              Code:
              <form method="post" action="<c&#58;url value="search.xyz"/>">
                    your product search form stuff
              </form
              
              <form method="post" action="<c&#58;url value="login.xyz"/>">
                     your login form stuff
              </form>
              with the action in each case specifiying the url for the controller that handles the form, as mentioned in the previous post.
              Here xyz is the suffix that gets handled by your servlet (if that's how your servlet mapping works).

              These two controllers handle the form input, and each send their response to their own results view.

              Hope that helps - post again if not.

              Comment


              • #8
                Chris,

                That's exactly what I want. And I can handle it as you suggested, using a different URL in each action parameter (am I correct in believing that that would then direct control to whichever Controller was mapped to the specified URL?).

                However, does that preclude the use of Command objects, Validators, etc.? Could I press you and ask how the bean configuration might look? Thanks, again, in advance!

                Brian

                Comment


                • #9
                  Note that if you need to prepopulate all forms of the view (or validate them all at once or something), one way to do this is have a single Controller and a single Command object that contains the fields for all of your forms.

                  In your view you can have a submit with different names for each form (but technically you have a single form in your HTML). For example, I have:

                  Code:
                  <form ....
                  
                  <input type="submit" name="submit.update" value="Update"/>
                  <input type="submit" name="submit.delete" value="Delete"/>
                  </form>
                  Then in the onSubmit for your Controller you can find out which submit was clicked and do the appropriate action. For my example:

                  Code:
                  if &#40;request.getParameter&#40;"submit.update"&#41; != null&#41; &#123;
                     // do stuff for update
                  &#125; else if &#40;request.getParameter&#40;"submit.delete"&#41; != null&#41; &#123;
                     // do stuff for delete
                  &#125;
                  This may be overkill for what you want to do (or even problematic due to validatation), though, and you may want to stick with the multiple controller solution.

                  Comment


                  • #10
                    The suggestion in the previous post is a useful option in some cases. However the problem is that it makes it awkward to mix and match forms in your pages.
                    If you want formA in a dozen pages, and formB in a dozen other pages, and both formA and formB in a further half dozen pages, you can't do it without some complex & messy conditional logic in your jsp.
                    The jsp is much cleaner if you just include the jsp files for the forms you want in that page.

                    However the problem then is that pre-population of form fields is difficult, if not impossible. If you're happy with blank form fields, or fixed defaults every time the form appears, then it's OK.

                    The issue here is how you arrive at the view that has the form. If you're coming from the controller that handles the form (e.g. you went to that controller with a get, so it knows it's a request for the form, not a form submission), then you have all the facilities that offers, to create a form backing object, pre-populate it, set up reference data, etc. etc.
                    If you arrive at the view that has the form via a diffenent controller, that knows nothing about this form, then you don't have these facilities, and all you can do is present the blank form (with standard defaults if required).

                    When you submit the form however, you willl always be going to the controller that handles the form (via the action url), usually with a post, so the controller knows it's a form submission. Then all the standard things happen, i.e. creation, population and validation of the form backing object, followed by execution of onSubmit (provided the object is valid).

                    This is documented in the JavaDoc for AbstractFormController, in the section headed Workflow. Steps 1-7 are for a form request (get) and will never be executed in the scenario we are considering; steps 8-14 are for a form submission (post), and will be executed.

                    As for the bean configuration, I don't think it would be any different to the 'standard' set up of using the controller to handle the form request and the form submission. The only difference is you're not using the controller to handle the form request. That won't affect the bean configuration.

                    Don't forget that with this set up, you can't use spring:bind tags in the form used in multiple pages for data entry. But of course you can use them in the form(s) used by the controller to display errors or success.

                    Hope this helps. Ask again if not.

                    Comment


                    • #11
                      Chris,

                      Perfect. Thanks! And thanks to everyone else, as well - much appreciated. Good luck with your own projects.

                      Brian

                      Comment


                      • #12
                        Late to the thread, but I solved it this problem with two custom tags like this:-

                        Code:
                        <html&#58;hasNoErrors command="loginCommand">
                            <td><fmt&#58;message key="login.field.username"/> &#58;</td>
                            <td>
                                 <input type="text" name="username">
                            </td>
                        </html&#58;hasNoErrors>
                        <html&#58;hasErrors command="loginCommand">
                            <td><fmt&#58;message key="login.field.username"/> &#58;</td>
                            <spring&#58;bind path="loginCommand.username">
                                <td>
                                    <input type="text" name="username" value="<c&#58;out value="$&#123;status.value&#125;"/>">
                                </td>
                             </spring&#58;bind>
                        </html&#58;hasErrors>
                        Where each tag extends HtmlEscapingAwareTag and uses the following code to determine if errors exist:-

                        Code:
                        String resolvedName = ExpressionEvaluationUtils.evaluateString&#40;"command", command, pageContext&#41;;
                        Errors errors = getRequestContext&#40;&#41;.getErrors&#40;resolvedName, isHtmlEscape&#40;&#41;&#41;;
                                
                        if &#40;&#40;errors != null&#41; && &#40;errors.hasErrors&#40;&#41;&#41;&#41; 
                        &#123;
                            pageContext.setAttribute&#40;ERRORS_VARIABLE_NAME, errors&#41;;
                            return &#40;true&#41;;
                        &#125;
                                
                        return &#40;false&#41;;
                        Bob

                        Comment


                        • #13
                          Two forms on the page

                          Originally posted by cmgharris
                          We do something similar, it's not a problem. You can have different bits - headers, footers, forms, whatever - included in your views with include lines.
                          The form action will send the form parameters to the appropriate controller to handle it.
                          The only thing to be aware of is that if the form uses <spring:bind> tags to display errors etc., you have to have the formbacking object with the errors instance in the model, otherwise you get an error.
                          So you may need two versions of your form jsp: one without the spring bind tags, just for entry, which can be used in any view; and one with the error display handling which is used by the controller that handels the form's input.
                          Unless there is a better way of handling this issue?
                          This looks very close to what I am trying - but failing - to achieve. Main.jsp includes AA.jsp and BB.jsp. AA and BB each have their own submit button and controller. Everything has worked until I integrated a validator. The error message would be displayed with just AA.jsp. In order to see the whole page, I can redirect output to main.jsp, but I need to understand the mechanism of passing the errors through main.jsp. At the moment, control passes through formBackingObject and a new command object is created and the user's input and the validator's errors are lost.

                          So, in summary, click submit on AA.jsp, AA controller manages the flow and forwards the errors to view main.jsp which forwards the submit to AA.jsp and BB.jsp. How to detect and manage the errors on the second entry to AA.jsp ? Thank you for any comments.

                          ======
                          Martin

                          Comment


                          • #14
                            Another solution

                            I realise that this is a very old tread, however I have a simple solution which others who find this using google may try.

                            I set up separate form controllers for each of my separate forms and then include them in any JSP using the <jsp:include page="" />

                            For example, if I wanted the ability to include a login form on any page I would create a small jsp like so:


                            HTML Code:
                            <form:form method="post" commandName="account">
                              <form:input path="username" />
                              <form:password path="password" />
                              <input type="submit" value="Log In" />
                            </form:form>

                            And a login handler:

                            Code:
                            <bean name="/login.do" class="com.myApp.web.actionHandler.LoginHandler">
                              <property name="sessionForm" value="true"/>
                              <property name="commandName" value="account"/>
                              <property name="commandClass" value="com.myapp.domain.Account"/>
                              <property name="formView" value="/jsp/login.jsp"/>
                              <property name="errorView" value="/jsp/login_error.jsp"/>
                              <property name="successView" value="/profile/profileView.view"/>
                              <property name="accountManager" ref="accountManager"/>
                              <property name="securityManager" ref="securityManager"/>
                            </bean>
                            Then in a page I wanted the form to appear in I would add the following:

                            HTML Code:
                            <jsp:include page="/login.do" />
                            The advantage of this method is that the form handler is called when the form is first shown, so it can be pre-populated if required.

                            The disadvantage is that if the form submission fails validation then the browser would normally be redirected to the form view, which would just be the tiny JSP above. A solution to this is to include a separate errorView which is a complete JSP page (as above) and redirect to that if validation fails.

                            Another solution might be to catch the referring page when in the form controller and use that as the error view. I haven't tried this, so I'm not sure if it is possible/easy - I'm just speculating.

                            Disclaimer - I have only been developing with Spring for about 4 weeks, so the above may not be considered best practice for reasons beyond my knowledge. If this is the case, please let me know!

                            Comment


                            • #15
                              jsp:include equivalent with freemarker

                              Hi,

                              i have the same need as you with multiple forms in a single page, and i would like to do like you, except my technology view is not jsp, but freemarker.

                              I would like to do an equivalent jsp:include with freemarker, but i have not found the way to do it. I tried to use <@include_page> available since Freemarker 2.3.15 but it does not work on my Spring MVC application.

                              Have you got an idea? How could i do?

                              Thanks in advance.

                              Comment

                              Working...
                              X