2010-09-08 4 views
0

Laissez-moi présenter mon problème en fournissant une partie du code en question.Spring 3 MVC: Problème de liaison aux champs de formulaire de liste sur soumettre

D'abord mon objet formulaire:

public class OrgChartForm { 

    List<OrgChartFormElement> orgChartFormElements; 

    public OrgChartForm() { 
     orgChartFormElements = new ArrayList<OrgChartFormElement>(); 
    } 

    private OrgChartFormElement createOrgChartFormElementFromMprsStructureYear(MprsStructureYear structureYear){ 
     OrgChartFormElement element = new OrgChartFormElement(); 
     element.set.... // populate element based on attribute values from structureYear param 
     return element; 
    } 

    public void createOrgChartFormElements(List<MprsStructureYear> structureYears) { 
     orgChartFormElements = new ArrayList<OrgChartFormElement>(); 
     for(MprsStructureYear structureYear:structureYears){ 
      orgChartFormElements.add(createOrgChartFormElementFromMprsStructureYear(structureYear)); 
     } 
    } 

    // expected getters and setters 
} 

Le formulaire contient une simple liste de OrgChartFormElement s

public class OrgChartFormElement { 
    private boolean selected; 
    private String elementLabel; 
    private Long id; 

    //default constructor, getters and setters 
} 

J'utilise context:component-scan et mvc:annotation-driven, donc mon contrôleur ressemble à:

@Controller 
public class OrganisationStatusController{ 

    @Autowired(required=true) 
    // dependencies here 

    @RequestMapping(value="/finyear/{finyearId}/organisationstatus", method=RequestMethod.GET) 
    public String createRootOrg(@PathVariable(value="finyearId") Long finyearId, Model model) throws Exception { 
     List<MprsStructureYear> orgStructuure = getOrganisationService().getOrganisationStructureForFinyear(finyearId); 

     OrgChartForm orgChartForm = new OrgChartForm(); 
     orgChartForm.createOrgChartFormElements(orgStructuure); 
     model.addAttribute("orgChartForm", orgChartForm); 

     return "finyear/organisationchart/view"; 
    } 

    @RequestMapping(value="/finyear/{finyearId}/organisationstatus", method=RequestMethod.POST) 
    public String createRootOrg(@PathVariable(value="finyearId") Long finyearId,@ModelAttribute("orgChartForm") OrgChartForm orgChartForm, BindingResult result, Model model) throws Exception { 
     System.out.println("Found model attribute: " + model.containsAttribute("orgChartForm")); 
     List<OrgChartFormElement> elements = orgChartForm.getOrgChartFormElements(); 
     System.out.println(elements); 
     return "redirect:/spring/finyear/" + finyearId + "/organisationstatus"; 
    } 

    // expected getters and setters 
} 

Le problème est avec le gestionnaire POST. Je me rends compte que cela ne fait pas grand chose maintenant, mais une fois que je l'aurai mis en pratique, je persisterai dans les valeurs soumises.

En ce moment, la sortie que je vois des deux déclarations sysout sont:

Found model attribute: true 
[] 

Voici mon extrait JSP:

<sf:form modelAttribute="orgChartForm" method="post"> 
    <c:forEach items="${orgChartForm.orgChartFormElements}" var="org" varStatus="status"> 
     <sf:hidden id="${org.id}field" path="orgChartFormElements[${status.index}].id"/> 
     <sf:input id="${org.id}hidden" path="orgChartFormElements[${status.index}].selected"/> 
     <c:out value="${org.elementLabel}"/>(<c:out value="${org.id}"/>) - <c:out value="${status.index}"/> 
    </c:forEach> 
    <input type="submit" value="Submit" /> 
</sf:form> 

Quand je fais la demande GET, le JSP rend, et je vois ma liste de champs de saisie de texte, avec les valeurs attendues, ce qui me dit que j'utilise correctement les balises printanières. Toutefois, lorsque je soumets, l'objet de sauvegarde de formulaire déclaré en tant que paramètre (orgChartForm) dans la méthode du gestionnaire POST est initialisé, mais tout est initialisé par défaut. Je ne sais pas où sont passées les données soumises! Il semble que springMVC le perde, et construit simplement un nouvel objet.

J'ai utilisé ce modèle de manière extensive dans cette application sans aucun problème. Ça ne marchera pas ici. Je me rends compte que c'est un cas particulier dans mon application où le champ de formulaire n'est pas atomique mais une liste, Cependant c'est vraiment me confondre que les données se lient dans la demande GET, mais pas sur le POST.

Merci d'avance pour les pointeurs!

Répondre

0

Je pense que le problème est que vous essayez de lier un nombre arbitraire de champs de formulaire à une ArrayList, qui est une liste qui a une taille prédéterminée. Spring a quelque chose appelé AutoPopulatingList qui est spécialement conçu à cet effet. S'il vous plaît jeter un oeil à ce lien pour plus d'informations sur la façon de l'utiliser: http://blog.richardadamdean.com/?p=12

0

Je pense que vous aurez besoin d'écrire PropertyEditorSupport pour votre classe. Voici l'exemple pour votre référence.

public class SampleEditor extends PropertyEditorSupport { 

private final SampleService sampleService; 

public SampleEditor(SampleService sampleService, Class collectionType) { 
    super(collectionType); 
    this.sampleService = sampleService; 
} 

@Override 
public void setAsText(String text) throws IllegalArgumentException { 
    Object obj = getValue(); 
    List list = (List) obj; 
    for (String str : text.split(",")) { 
     list.add(sampleService.get(Long.valueOf(str))); 
    } 
} 

@Override 
public String getAsText() { 
    return super.getAsText(); 
} 

}

Dans le contrôleur, vous devez lier l'aide @InitBinder comme suit:

@InitBinder 
protected void initBinder(HttpServletRequest request, WebDataBinder binder) { 
    binder.registerCustomEditor(List.class, "list", new SampleEditor(this.sampleService, List.class)); 
} 

Espérons que cela résoudra votre problème.

Questions connexes