Search code examples
javaspringjspspring-mvcspring-annotations

Spring MVC form - No items in dropdown list?


My form has one text field and one dropdown list.When my form loads first time there is a list of values in the dropdown list.

If I am submitting the form , and my form has any errors , I am trying to return the same form to show the errors and to resubmit the missed data.

But if my form reloads through the POST method of controller , there is no values in the dropdown list.

My spring controller ,

@Controller
public class FormController {

    private ListStore getList;

    @RequestMapping(value="/ApplicationForm.html",method=RequestMethod.GET)
    public String displayForm(@ModelAttribute UserData userData,ModelMap map){

        map.addAttribute("age",(ArrayList<String>)getList.ageList());
        return "ApplicationForm";
    }

    @RequestMapping(value="/ApplicaitonForm.html",method=RequestMethod.POST)
    public String displayFormDetails(@Valid UserData data,BindingResult result,ModelMap map,@RequestParam(value="name",required=true) String name,@RequestParam("age") String age){

        if(result.hasErrors()){
            System.out.println("It has some errors !!!!!!!!");
            return "ApplicationForm";
        }
        map.addAttribute("name", name);
        map.addAttribute("age", age);

        return "DisplayFormDetails";
    }
}

My ListStore class will be,

public class ListStore {

    public List<String> ageList(){
        LinkedList<String> list = new LinkedList<String>();
        list.add("20 to 25 years");
        list.add("25 to 35 years");
        list.add("above 35 years");
        return list;
    }
 }

How to restore the values in the dropdown list , when my form reloads through the POST method of the controller ?

But I solved this issue by adding map.addAttribute("age",(ArrayList<String>)getList.ageList()); as in my code as,

    if(result.hasErrors()){
        System.out.println("Form has some errors !!!!!!!!");
        map.addAttribute("age",(ArrayList<String>)getList.ageList());
        return "ApplicationForm";
    }

But is there any other way to do this easily ?

Hope our stack members will help me.


Solution

  • I'm usually calling display method from action (POST) method to avoid code duplication. See your slightly modified code below. I've also made small change in your code to follow Post/Redirect/Get pattern.

    @Controller
    public class FormController {
    
        private ListStore getList;
    
        @RequestMapping(value="/ApplicationForm.html", method=RequestMethod.GET)
        public String displayForm(@ModelAttribute UserData userData, Model model){
    
            model.addAttribute("age", getList.ageList());
            return "ApplicationForm";
        }
    
        @RequestMapping(value="/ApplicaitonForm.html", method=RequestMethod.POST)
        public String processForm(@Valid UserData data, 
                                  BindingResult result, 
                                  Model model, 
                                  @RequestParam(value="name", required=true) String name, 
                                  @RequestParam("age") String age, 
                                  RedirectAttributes redirectAttributes) {
    
            if(result.hasErrors()){
                System.out.println("It has some errors !!!!!!!!");
                return displayForm(data, model); /* THIS IS THE TRICK :) */
            }
    
            redirectAttributes.addFlashAttribute("name", name);
            redirectAttributes.addFlashAttribute("age", age);
    
            return "redirect:/DisplayFormDetails.html"; // Redirect here to follow Post/Redirect/Get pattern
        }
    
        @RequestMapping(value="/DisplayFormDetails.html", method=RequestMethod.GET)
        public String displayFormDetails(Model model){
            // name and age are already in model due to use of RedirectAttributes
            return "DisplayFormDetails";
        }
    }