Announcement Announcement Module
Collapse
No announcement yet.
Ajax form submit using Spring Javascript Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Ajax form submit using Spring Javascript

    I have been trying to add the Ajax for form submission with a SWF application using tiles. I have tried two methods so far:

    <a id="addPersonLink" href="portfolio-flow.htm?execution=${flowExecutionKey}&_eventId=ad dPerson">+ Person</a>
    <script type="text/javascript">
    Spring.addDecoration(new Spring.AjaxEventDecoration({
    elementId: "addPersonLink",
    event: "onclick",
    formId:"addPersonForm",
    params: {fragments:"productList"}
    }));
    </script>

    and the direct call:

    <input id="addBusiness" type="submit" name="_eventId_addBusiness" value="addBusiness" onclick="Spring.remoting.submitForm('addBusiness', 'addBusinessForm', { fragments:'clientList' }); return false;" />

    Both methods don't use an ajax call of the clientList fragment but refresh the whole page. The first AjaxEventDecoration method with the formId attribute removed acts as an ajax call as expected but form items do not submit.

    Is this expected behaviour? Does Spring Javascript not support Ajax calls on form submit?

  • #2
    Please use [ code][/code ] tags when using code.

    Is this expected behaviour? Does Spring Javascript not support Ajax calls on form submit?
    It does but I think not in the way you expect it to do. The fragment has to be part of the current page, else it doesn't work. I suggest that you take a look at the sample application, that shows a submit/link with a partial page refresh.

    Comment


    • #3
      Sorry about the missing code tags. New to the forums and still working out how the posting works.

      What do you mean the code needs to be in the current page? Currently I am testing a form submit where i add a person to an application. there is one tile that represents the added clients. In the same page there is a form with a first name and last name field and a submit like the ones i posted. I am trying to submit the form and update the personList fragment. If i trigger the transition with a link the personList updates if i add the formId all of the tiles updated.

      I have looked at the swf-booking-mvc sample app and didn't see an example that posted the form that way. Is there a better example than that?

      Comment


      • #4
        Well your link is never going to work, that is just a GET request, it doesn't do anything for you.

        Also instead of a submit I think you need to use a normal button.

        What do you mean the code needs to be in the current page?
        I never mentioned CODE I mentioned a FRAGMENT. So the fragment you define must be part of the current page, i.e. in your tiles definition. Else it isn't going to work, but as you already mentioned it is part of your current page, so that shouldn't be the problem.

        Comment


        • #5
          I have made a little progress in figuring out what is going on with this.

          I am now able to submit a form and update a tile.

          When just calling a transition in SWF with a get link:

          Code:
              <a id="addPersonLink" href="portfolio-flow.htm?execution=${flowExecutionKey}&_eventId=addPerson">+ Person</a> 
          <script type="text/javascript">
          Spring.addDecoration(new Spring.AjaxEventDecoration({
          elementId: "addPersonLink",
          event: "onclick",
          params: {fragments:"productList"}
          }));
          The fragments resolve as expected.

          When submitting a form:
          Code:
          <input type="submit" id="addPerson" name="_eventId_addPerson" value="AddPerson"  onclick="Spring.remoting.submitForm('addPerson', 'addPersonForm', params: {fragments:"clientList"}); return false;" />
          or

          Code:
                  <input type="submit" id="addPerson" name="_eventId_addPerson" value="AddPerson"   />
          <script type="text/javascript">
              Spring.addDecoration(new Spring.AjaxEventDecoration({
                  elementId: "addPerson",
                  event: "onclick",
                  formId:"addPersonForm",
                  params: {fragments:"clientList"}
              }));
          </script>
          The tiles doesn't automatically update until I add <div id="clientList"></div> around the content.

          The auto-resolving of the tiles seems to fail even though the server is sending back the update correctly. If I discover anything else that resolves this i will post later.

          Comment


          • #6
            controller

            i have been trying to get this to work as well without much success.

            what are you using on the server side? which controller, and what do your servlet and tiles configuration look like? if you don't mind sharing. thanks.

            Comment


            • #7
              Originally posted by pgibbons View Post
              i have been trying to get this to work as well without much success.

              what are you using on the server side? which controller, and what do your servlet and tiles configuration look like? if you don't mind sharing. thanks.
              Not sure how far along you are so I'll give you as much as i can. I haven't included any of the web flow stuff as it is pretty standard. Let me know if this is enough or if you still have issues. My last post has a little explanation about how to call the ajax from a form. the standard link stuff was fairly solid. Good luck!

              in the web.xml you need to add the ResourceServlet

              Code:
                  
              <servlet>
                      <servlet-name>Resource Servlet</servlet-name>
                      <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
                  </servlet>
                  <servlet-mapping>
                      <servlet-name>Resource Servlet</servlet-name>
                      <url-pattern>/resources/*</url-pattern>
                  </servlet-mapping>
              Along with that in your tile page that you are triggering the ajax from add:

              Code:
                  <script type="text/javascript" src='<c:url value="/resources/dojo/dojo.js" />'></script>
                  <script type="text/javascript" src='<c:url value="/resources/spring/Spring.js" />'></script>
                  <script type="text/javascript" src='<c:url value="/resources/spring/Spring-Dojo.js" />'></script>
              in your application config add:

              Code:
              <flow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" >
                      <flow:flow-location path="/WEB-INF/flows/application-flow.xml"/>
                  </flow:flow-registry>
                  <flow:flow-builder-services id="flowBuilderServices" view-factory-creator="viewFactoryCreator"/>
                  <bean id="viewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
                      <property name="viewResolvers">
                          <list>
                              <ref bean="tilesAjaxViewResolver"/>
                          </list>
                      </property>
                  </bean>
                  <bean id="tilesAjaxViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedViewResolver">
                      <property name="viewClass" value="org.springframework.webflow.mvc.view.FlowAjaxTilesView">
                      </property>
                  </bean>
                  <bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
                      <property name="viewResolvers" ref="tilesAjaxViewResolver" />         
                  </bean>
                 <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
                      <property name="definitions">
                          <list>
                              <value>/WEB-INF/layouts/layouts.xml</value>
                              <value>/WEB-INF/jsps/views.xml</value>
                          </list>
                      </property>
                  </bean>

              Comment


              • #8
                Just JS/Dojo, no Web Flow

                Hey thanks for posting your information. I have a slightly different setup, as I'm not using Web Flow.

                Below is my set up, I have a decoration as such:

                Code:
                <a id="searchResultsLink" href="search.html">Search AJAX Test</a>
                <script type="text/javascript">
                Spring.addDecoration(new Spring.AjaxEventDecoration({
                					        elementId: "searchResultsLink",
                					        event: "onclick",      
                					        params: { fragments: "copyright" }
                					    }));
                </script>
                this is on my "home" page. on the home page i have a tile fragment called "copyright" as well.

                "search.html" is setup in my servlet xml as such:

                Code:
                <bean name="/search.html" class="com.controller.SearchController"/>
                corresponding to:

                Code:
                	public ModelAndView handleRequest(HttpServletRequest request,
                			HttpServletResponse response) throws ServletException, IOException {
                
                
                		ModelAndView modelAndView = new ModelAndView("search.results");
                
                
                		return modelAndView;
                	}

                I have "search.results" tile setup as well. It basically points to a jsp that only has static text now (such as "this is search results page"). Is this the right way to setup a controller for an Ajax call?


                When I click on the link setup above (decoration at the beginning of this post), nothing seems to happen on the UI. The controller is being invoked (I tried putting a system out to verify). But nothing on the UI.

                If I replace "search.html" with a non existing link, I get a pop up with a 404 error.
                If I replace "search.html" with something like "http www cnn dot com/", I am redirected to cnn.com. (Note the quoted link above is a valid cnn url, I had to break it up, because I am not allowed to post links.)

                What I expected to happen is that the "copyright" tile fragment to be replaced with the html returned from cnn.com.

                Please let me know if anyone sees something that I am doing wrong. I am new to Spring as well as Spring JS. Thanks in advance.
                Last edited by pgibbons; Sep 2nd, 2008, 09:57 PM.

                Comment


                • #9
                  appears to be working

                  Ok, it appears to be working now:

                  Code:
                  <a id="searchResultsLink" href="search.html">Search AJAX Test</a>
                  <script type="text/javascript">
                  Spring.addDecoration(new Spring.AjaxEventDecoration({
                  					        elementId: "searchResultsLink",
                  					        event: "onclick",      
                  					        params: { fragments: "copyright" }
                  					    }));
                  </script>
                  It seems the fragments "copyright" had to the "id" of a "div" and NOT the name of the tile fragment.

                  This is contrary to what I've read in other threads in this forum. I got the impression that the fragments were tiles. But it seems div id is working, but not tile name.

                  It works. But can anyone explain? Where is the documentation (detailed) for Spring JS, I wasn't able to locate it. Thanks.

                  Comment


                  • #10
                    Originally posted by pgibbons View Post
                    Ok, it appears to be working now:

                    Code:
                    <a id="searchResultsLink" href="search.html">Search AJAX Test</a>
                    <script type="text/javascript">
                    Spring.addDecoration(new Spring.AjaxEventDecoration({
                    					        elementId: "searchResultsLink",
                    					        event: "onclick",      
                    					        params: { fragments: "copyright" }
                    					    }));
                    </script>
                    It seems the fragments "copyright" had to the "id" of a "div" and NOT the name of the tile fragment.

                    This is contrary to what I've read in other threads in this forum. I got the impression that the fragments were tiles. But it seems div id is working, but not tile name.

                    It works. But can anyone explain? Where is the documentation (detailed) for Spring JS, I wasn't able to locate it. Thanks.
                    Yeah that is the problem i was talking about in my previous entry.

                    I havent had a chance to work that out yet. I am a bit flat out without it but am going to try and debug with the uncompressed js and see if i can figure it out. Unfortunately if I dont figure it out by friday it will have to wait a week because i am going on holidays. If i get a chance to work through it i will post again. You only need the div with id if you are using a form submit not a regular get request on a link.

                    Comment


                    • #11
                      Hi,

                      As far as I understand it, the fragments parameter in the JavaScript Spring.AjaxEventDecoration call ARE the tiles which will be rendered (org.apache.tiles.Attribute). Check out AjaxTilesView.java from the springframework-js jar. If you use the FlowAjaxTilesView.java then the fragments in the flow configuration override that parameter.

                      The response will contain the rendered tiles. That response will be handled by handleResponse in Spring-Dojo.js , both in the GET and POST scenario.

                      In that response handling the new DOM nodes from the response are extracted and the old nodes are replaced by the new ones. (If you didn't use a modal dialog) These DOM nodes are for example div's.

                      I don't know if this helps clarify the difference on the tiles and divs thing during fragments rendering.

                      Regards,
                      Bram Bruneel

                      Comment


                      • #12
                        Originally posted by Brambo View Post
                        Hi,

                        As far as I understand it, the fragments parameter in the JavaScript Spring.AjaxEventDecoration call ARE the tiles which will be rendered (org.apache.tiles.Attribute). Check out AjaxTilesView.java from the springframework-js jar. If you use the FlowAjaxTilesView.java then the fragments in the flow configuration override that parameter.

                        The response will contain the rendered tiles. That response will be handled by handleResponse in Spring-Dojo.js , both in the GET and POST scenario.

                        In that response handling the new DOM nodes from the response are extracted and the old nodes are replaced by the new ones. (If you didn't use a modal dialog) These DOM nodes are for example div's.

                        I don't know if this helps clarify the difference on the tiles and divs thing during fragments rendering.

                        Regards,
                        Bram Bruneel
                        Yeah from what I have read it is supposed to work that way. I did a quick test with and without the div and changing the id and stuff and have figured out how to cause the refresh and how to make it stop.

                        This only happens with form submit not standard get links.

                        The tile that I am using is called clientList. I originally thought I had to include a div with and id attribute of clientList, but it seems I only have to include a div with an Id of any value around the content. If I include a div with a name property only, it doesn't work.

                        The first submit doesn't get an update the second throws an error from the spring-dojo.js file. I am assuming if this is not a common problem that there is something about the layout that is causing the handleResponse throw an error. Possibly pgibbons is having the same issue?

                        I will try and debug it using the uncompressed spring-dojo and see if i can find what is causing the issue.

                        Comment


                        • #13
                          Originally posted by walterdeane View Post
                          The tile that I am using is called clientList. I originally thought I had to include a div with and id attribute of clientList, but it seems I only have to include a div with an Id of any value around the content. If I include a div with a name property only, it doesn't work.
                          Yes the replacement of the DOM elements will probably be based on the id's.

                          Originally posted by walterdeane View Post
                          The first submit doesn't get an update the second throws an error from the spring-dojo.js file. I am assuming if this is not a common problem that there is something about the layout that is causing the handleResponse throw an error. Possibly pgibbons is having the same issue?
                          hmm, first submit works and second doesn't ... does the first submit event trigger a state transition perhaps?

                          Originally posted by walterdeane View Post
                          I will try and debug it using the uncompressed spring-dojo and see if i can find what is causing the issue.
                          Debugging is the next thing to do and also check out the HTTP requests and responses with firebug while you are at it. The second POST might return data with DOM elements which can't be replaced, this will give a js error. I encountered that because some of my responses returned a standard error page.

                          Comment


                          • #14
                            Hi. Did u find any solution?
                            I have this environment:
                            • Spring 2.5.6
                            • Spring webflow 2.0.7
                            • JVM 1.5 and 1.6
                            • Tomcat 5.5 and 6.0

                            I have a classic Spring MVC application done by Controller, SimpleFormController and AbstractWizardFormController. I need to add some Aajax behaviours above all to my AbstractWizardFormController. I downloaded spring webflow 2.0.7 and i'ld love to use only Spring-Js framework.
                            Now i'ld like to realize this scenario (if possible but i think it's possible) in my AbstractWizardFomController:
                            • The user comples the required fields in first page of my page (the _target0 page)
                            • He/She clicks on a link or button or submit that goes on the _target1 page
                            • I wanna open a popup where the user can do some work (i.e checks some checkboxes)
                            • when on the _target1 page the user clicks on confirm button i wanna do a submit to the _target0 page and refresh only a partial part od my page showing to the user the choices

                            Now...in my myapp-servlet.xml file i added the TilesViewResolver that is:

                            Code:
                            	<bean id="tilesViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedViewResolver">
                            		<property name="viewClass" value="org.springframework.webflow.mvc.view.FlowAjaxTilesView"/>
                            	</bean>
                            Now i have a first problem: how can i do a submit with Spring Js framework?
                            In my jsp page i did this thing:


                            Code:
                            <a href="createCeItem.controller?_popu1&amp;folderId=<%=request.getParameter("folderId") %>" id="scegliCategorie" name="scegliCategorie" title="<fmt:message key="chooseCateogries"/>" class="button"><fmt:message key="chooseCateogries"/></a>
                            <script type="text/javascript">
                            /*<![CDATA[*/
                            Spring.addDecoration(new Spring.AjaxEventDecoration({
                            				elementId: "scegliCategorie",
                            			        event: "onclick",
                            				popup: true,
                            				params: {fragments: "scegliCategorie"}		
                            			}));
                            /*]]>*/
                            </script>
                            The fragments params is a tiles so defined:
                            Code:
                            <definition name="cePopUpHome" template="/WEB-INF/ceTilesLayout/cePopupLayout.jsp">
                             <put-attribute name="head" value="/WEB-INF/jsp/ce/generic/head.jsp" />
                             <put-attribute name="corpo" value="" />
                            </definition>	
                            
                            <definition name="elencoCategorie" extends="cePopUpHome">
                              <put-attribute name="corpo" value="/WEB-INF/jsp/ce/item/elencoCategorie.jsp" />
                            </definition>
                            I "deceived" my abstracwizardform controller by overriding the isSubmissionForm method and the getTargetPage method in order to do a "submit" when the user clicks on the href. I did this thing:

                            Code:
                            @SuppressWarnings("unchecked")
                            protected final int getButtonFromRequest(HttpServletRequest request, String value) {
                            
                                Enumeration<String> paramNames = request.getParameterNames();
                                while (paramNames.hasMoreElements()) {
                            	String paramName = (String) paramNames.nextElement();
                            	if (paramName.startsWith(value)) {
                            	String val = paramName.substring(value.length(), paramName.length());
                            	return Integer.parseInt(val);
                                    }
                                 }
                                return -1;
                            	}
                            
                            @Override
                            protected boolean isFormSubmission(HttpServletRequest request) {
                            
                              if (getButtonFromRequest(request, "_popup") != -1) {
                            			
                            	return true;
                              }
                               return super.isFormSubmission(request);
                            }
                            
                            @Override
                            protected int getTargetPage(HttpServletRequest request, Object command, Errors errors, int currentPage)  {
                            
                              int popupButton = getButtonFromRequest(request, "_popup");
                              if (popupButton > -1) {
                            			
                                String requestUri = request.getServletPath();
                                String queryString = request.getQueryString();
                                requestUri = requestUri.endsWith("?") ? requestUri : requestUri+"?";
                                String completeUri = requestUri+queryString;
                                String msg = "E stata richiamata questa uri: "+completeUri+" sopprimo le validazioni ed apro la popup";
                                LoggerUtil.traceInfo(logger, msg);
                                setAllowDirtyForward(true);
                                return popupButton;
                               } else {
                            	if( isAllowDirtyForward() ){
                            				
                            	  setAllowDirtyForward(false);
                                    }
                            	return super.getTargetPage(request, currentPage);
                               }
                            }
                            But, altough the abstractwizardformcontroller thinks it's a submit, this is not a real HTML submit so, correctly, spring will not bind the elements in command; anyway i'm able to open a popup (it seems strange but this popup doesn't have any stylesheet and i don't know why..it simply appears trasparent with the checkboxes i want); this problem is destroying me.
                            Do u have any suggestion about how i could implement this scenario?

                            Comment

                            Working...
                            X