Question

I have a form declared as follows:

  <form id="reply-form-frm" novalidate="novalidate" action="/reply/responsive" method="POST">
                [@spring.bind "model.form"/]

                [@spring.bind "model.form.message" /]

                <label for="${spring.status.expression}" class="clearfix" data-error="Please enter a message">
                    <span class="label-text">Your message</span>
                    <span class="set-right required-flag">Required</span>
                </label>

                <p class="input-error[#if spring.status.errorMessages?size > 0] reveal-error[#else] hide-error[/#if]">
                    [#if spring.status.errorMessages?size > 0]
                      <span>[#list spring.status.errorMessages as error]${error}[/#list]</span>
                    [/#if]
                </p>
                [@spring.formTextarea "model.form.message", 'aria-required="true" required="required" data-clear="true"' /]
   </form>

Some additional fields are rendered in the same way. The model the form receives is:

model: {
  form: {
    senderName: "hahahahaha",
    senderEmail: "asd@asd.es",
    advertId: 1000011793,
    optInMarketing: false,
    advertClickSource: "natural"
}

And my controller has this mapping method:

 public ModelAndView sendReplyResponsive(@ModelAttribute("model.form") ReplyForm replyForm,
                                            BindingResult bindingResult) {
    //TODO: content irrelevant ...
 }

The issue is that when the form renders, the elements map to "form.message" instead of "model.form.message" and my controller can't find the ReplyForm object on post.

Any idea on how can I force Spring to use "model.form.message" as the name?

Was it helpful?

Solution

Short answer - There is no possiblity to force spring to use "model.form.message" as the name.

Long answer: Spring always strip first part of name ("model" in your case) it is not dependent from presentation engine this logic is coded inside org.springframework.web.servlet.support.BindStatus#BindStatus. Common approach is use same model for render and binding, in you case you should:
1. use "model" class for binding:

public ModelAndView sendReplyResponsive(@ModelAttribute("model") ReplyModel model, BindingResult bindingResult) {
    ReplyForm replyForm = model.getForm();
    //TODO: content irrelevant ...
}

Or 2. expose ReplyForm as independent model attribute:

<form id="reply-form-frm" novalidate="novalidate" action="/reply/responsive" method="POST">
    [@spring.bind "form.message" /]

    <label for="${spring.status.expression}" class="clearfix" data-error="Please enter a message">
        <span class="label-text">Your message</span>
        <span class="set-right required-flag">Required</span>
    </label>

    <p class="input-error[#if spring.status.errorMessages?size > 0] reveal-error[#else] hide-error[/#if]">
        [#if spring.status.errorMessages?size > 0]
          <span>[#list spring.status.errorMessages as error]${error}[/#list]</span>
        [/#if]
    </p>
    [@spring.formTextarea "form.message", 'aria-required="true" required="required" data-clear="true"' /]
</form>

Model will be like:

model: {
  form: {
    senderName: "hahahahaha",
    senderEmail: "asd@asd.es",
    advertId: 1000011793,
    optInMarketing: false,
    advertClickSource: "natural"
    }
},
form: {
    senderName: "hahahahaha",
    senderEmail: "asd@asd.es",
    advertId: 1000011793,
    optInMarketing: false,
    advertClickSource: "natural"
}

If your "model" contains only form then there is no reason to keep it. And controller method will be:

public ModelAndView sendReplyResponsive(@ModelAttribute("form") ReplyForm replyForm,
                                            BindingResult bindingResult) {
    //TODO: content irrelevant ...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top