Spring MVC: mehrere @ModelAttribute in form handling-Aktion
Rahmen
Habe ich eine einfache Assoziation zwischen den beiden Entitäten - Category
und Email
(NtoM). Ich versuche das erstellen von web-Benutzeroberfläche zum durchsuchen und verwalten. Durchsuchen Sie die Kategorie und zum hinzufügen von e-mails in diese Kategorie, die ich verwenden controller verpackt mit @RequestMapping
mit der Kategorie-ID (UUID), also alle controller-Aktionen werden immer stattfinden, im Zusammenhang mit der Kategorie angegeben Pfad.
Benutze ich @ModelAttribute
pre-load-Kontext-Kategorie für die gesamte controller-Bereich.
Das problem
Dieser Ansatz funktioniert gut für die Auflistung und für die Anzeige der Formulare. Jedoch nicht auf form - Unterordnung- nach dem Debuggen ein wenig, fand ich heraus, dass der Formular-Daten überschreibt meine Kategorie @ModelAttribute
parameter.
In meinem code in der Methode save()
die category
ist nicht wirklich die Modell-Attribut geladen mit addCategory()
Methode, sondern ist gefüllt mit form-Daten (email
Modell ist auch aufgefüllt, und das ist richtig).
Ich bin auf der Suche nach der Lösung, die mir erlauben zu binden, bilden die Daten nur zu bestimmten @ModelAttribute
.
Ich gelesen habe in Spring MVC Dokumentation, dass die Reihenfolge der Argumente wichtig ist, aber ich befahl Ihnen, sich entsprechend zu Beispielen und immer noch klappt es nicht so wie erwartet.
Den code
Hier ist mein controller:
@Controller
@RequestMapping("/emails/{categoryId}")
public class EmailsController
{
@ModelAttribute("category")
public Category addCategory(@PathVariable UUID categoryId)
{
return this.categoryService.getCategory(categoryId);
}
@InitBinder
public void initBinder(WebDataBinder binder)
{
binder.registerCustomEditor(Set.class, "categories", new CategoriesSetEditor(this.categoryService));
}
@RequestMapping(value = "/create", method = RequestMethod.GET)
public String createForm(@ModelAttribute Category category, Model model)
{
//here everything works, as there is just a single @ModelAttribute
return "emails/form";
}
@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(
@ModelAttribute @Valid Email email,
BindingResult result,
Model model,
@ModelAttribute("category") Category category
) {
//saving entity, etc
//HERE! problem is, that response is bound BOTH to `email' and `category' model attributes
//and overrides category loaded in `addCategory()' method
return String.format("redirect:/emails/%s/", category.getId().toString());
}
}
Nur für den Fall, hier ist auch das Formular-code:
<form:form action="${pageContext.request.contextPath}/emails/${category.id}/save" method="post" modelAttribute="email">
<form:hidden path="id"/>
<fieldset>
<label for="emailName"><spring:message code="email.form.label.Name" text="E-mail address"/>:</label>
<form:input path="name" id="emailName" required="required"/>
<form:errors path="name" cssClass="error"/>
<label for="emailRealName"><spring:message code="email.form.label.RealName" text="Recipient display name"/>:</label>
<form:input path="realName" id="emailRealName"/>
<form:errors path="realName" cssClass="error"/>
<label for="emailIsActive"><spring:message code="email.form.label.IsActive" text="Activation status"/>:</label>
<form:checkbox path="active" id="emailIsActive"/>
<form:errors path="active" cssClass="error"/>
<form:checkboxes path="categories" element="div" items="${categories}" itemValue="id" itemLabel="name"/>
<form:errors path="categories" cssClass="error"/>
<button type="submit"><spring:message code="_common.form.Submit" text="Save"/></button>
</fieldset>
</form:form>
Hinweis: ich will nicht mehrere @ModelAttribute
s kommen aus der POST, die wollen nur irgendwie unterscheiden form das Modell aus zuvor generierten Attribut(s).
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich bin mir nicht sicher, ich verstehe das problem voll und ganz, aber mir scheint es, dass Sie wollen, Kategorie Objekt im Modell, wenn Sie das Formular anzeigen, aber nicht wollen, es zu sein geändert mit form post?
Wenn Sie angeben, die @ModelAttribute("Kategorien") in der argument Liste, die Sie im Grunde sagen, spring MVC zu binden, Formular-Daten zu den annotierten Objekt der mit dem parameter name "Kategorien".
Wenn Sie nicht möchten, dass das Objekt gebunden zu sein, lassen Sie es aus der Liste Parameter. Wenn Sie das ursprüngliche Objekt in der handler-Methode Holen Sie es manuell durch den Aufruf addCategory und Bereitstellung von id zugeordnet, die mit @PathVariable:
(PS. Wenn Sie sich einen Konverter, der konvertiert Long zu der Kategorie mit categoryService Sie können auch
@PathVariable("categoryId") Category category
zum anzeigen der Kategorie-Objekt path-variable statt der UUID, wenn Sie möchten, dass nehmen suchen Sie bei 7.5.5 Konfiguration eines ConversionService)(EDIT: entfernt Vorschlag zu name Modell anders als das wird nicht helfen, wie angemerkt in den Kommentaren, und fügte hinzu, Beispiel)
Persönlich, wenn ich brauchte diese Art von Verhalten (ein Objekt muss vorhanden sein, in das Formular beim anzeigen des Formulars, aber nicht verpflichtet, es bei der form geschrieben) würde ich nicht verwenden, ModelAttribute annotierte Methode zum Auffüllen des Modells. Stattdessen würde ich Auffüllen des Modells manuell bei der Anzeige des Formulars. Das ist ein bisschen mehr code (gut, der eine Zeile), aber ist weniger magisch und einfacher zu verstehen.
categories
als Attribut name, den ich verwendencategory
, die nicht überlappt werden mit einem Formular-Feld. Nur, dass die form-Felder sind alle gebunden an Kategorie object ist (beide Objekte müssenname
Eigenschaft zum Beispiel und Spring bindet Formularfeld Wert beidecategory.name
undemail.name
). Und für das Auffüllen von "manuell bei der Anzeige der form" - Ansatz - ich brauche die Kategorie in der Vorlage, handling-Aktion für das umleiten (man beachte die Letzte Zeilesave()
Aktion).