0

For example, I want to execute the "initRegister" method in Controller only after a user click the "Register" button in the page

@Controller
public class UserController
{

    @RequestMapping(method=RequestMethod.GET, value="/initPage.do")
    public String initPage(Model model)
    {
        return "home.jsp";
    }

    @RequestMapping(method=RequestMethod.GET, value="/initRegister.do")
    @ResponseBody
    public void initRegister(Model model)
    {
        model.addAttribute("reg", new RegisterForm());
    }
}

JQuery AJAX invoked by "Register" button: (show a small popup window for registration)

$.get('initRegister.do', function()
            { 
               $('body').append('<div>'
                   +'<form:form method="POST" modelAttribute="reg" '
                   + 'commandName="reg" action="register.do">'
                   + 'name: <form:input path="name"/>'
                   + '<input type="submit" value="Submit">'
                   + '</form:form>'
                   + '</div>');
            }
      );

However I got the following error in the browser when I access "http://localhost:8080/.../initPage.do"

Neither BindingResult nor plain target object for bean name 'reg' available as request attribute

The page works only if I move "model.addAttribute("reg", new RegisterForm());" to "initPage" method. But I don't need to create a RegisterForm instance until a uesr click "Register" button.

How to solve it?

wlin
  • 55
  • 2
  • 10
  • I guess you don't really have a choice. in you ajax, you are referencing modeAttribute="reg" so it is normal that you get that error. when the ajax gets executed in your page, you don't have any object "reg" – rptmat57 Sep 05 '12 at 20:49
  • Hi @rptmat57, you misunderstand the error. The AJAX code is invoked by the "Register" button in a CALLBACK function. I got the error when I type URL http://localhost:8080/.../initPage.do in the browser address bar and hit Enter. – wlin Sep 05 '12 at 21:27
  • 1
    how do you expect it to work if form:form is a serverside tag? it's bad idea to try to modify jsp from the client. Anyway, you *can* render the form with the Spring MVC and then submit the resulting html form with an AJAX post. – Boris Treukhov Sep 05 '12 at 21:41
  • Hi @BorisTreukhov, you misunderstand the code either. The example I gave is to show a popup window when a user click "Register" button. But I don't want to init the Form instance until user click "Register" button. Those HTML code is just to show a popup dialog, it doesn't matter if it is static html or dynamic html, what I need is to use AJAX to init the Form instance then show popup, I don't want to init all forms along with page loading because in my page I have many different buttons, each of which uses different Form class – wlin Sep 05 '12 at 21:58
  • 1
    @BorisTreukhov isn't the one that misunderstands the code... – digitaljoel Sep 05 '12 at 22:25
  • @wlin your alternatives are either to submit the resulting form (you can see the html form from the browser) with ajax http://stackoverflow.com/questions/1960240/jquery-ajax-submit-form or to post JSON directly, and process it with a specialized controller method that accepts json as `@RequestBody` – Boris Treukhov Sep 06 '12 at 10:44
  • @BorisTreukhov, thanks for you suggestion. If I submit the form with ajax like what you said, I have to give up the Spring form binding, right?(by not using form:form and form:input). – wlin Sep 06 '12 at 13:21
  • @wlin You can use Spring `form` tag when the page is rendered, and form binding will work(you can even do partial update with jQuery) - basically it does not matter for Spring how the http request was triggered - is it AJAX or submit button; then you receive the content of the updated form during your ajax post call - your controller need to return view name instead of void, and so you can set the inner html content of the current page's form with the content returned from the ajax post – Boris Treukhov Sep 06 '12 at 13:34
  • Oh, it is great approach. I've never think of returning the whole page content to an ajax call. Thank you so much @BorisTreukhov, you help me a lot! – wlin Sep 06 '12 at 14:09

1 Answers1

2

I'm assuming this code is contained within home.jsp

$.get('initRegister.do', function()
        { 
           $('body').append('<div>'
               +'<form:form method="POST" modelAttribute="reg" '
               + 'commandName="reg" action="register.do">'
               + 'name: <form:input path="name"/>'
               + '<input type="submit" value="Submit">'
               + '</form:form>'
               + '</div>');
        }
  );

You just can't do this. The form:form tag is processed on the server side when the initPage.do is rendered because it's a JSP tag and means nothing in javascript or html. I'm amazed you got as meaningful a message as you did.

When rendering JSP, it doesn't care if the tags are in HTML, javascript, wherever. If it sees a JSP tag it's going to perform appropriate processing. Trying to render the JSP code into the html page in response to an AJAX call just isn't going to work because the processing of the JSP tags must happen on the server.

Typically you will want to return an object in JSON format (or XML I guess) and use that in the javascript. have a look at the docs for jQuery's get command. Your function for the success handler has a 'data' parameter that will contain the response from your Ajax call. In order for that to work you should change the return type of initRegister from void to something else. You can use Jackson to do the conversion from POJO to JSON.

digitaljoel
  • 25,150
  • 14
  • 83
  • 114