retain model values in case of error and showing same thymeleaf template

Viewed 528

As per my understanding, model attributes are associated with every request and they can not survive multiple requests, until we add them as flashAttributes.

I have a simple controller method which shows a couple of options to user to select from. However, those options are being attached to thymeleaf template using model attributes.

<div class="input-group mb-3" th:each="ingredient : ${recipes.ingredients}">
<div class="input-group-prepend">
    <div class="input-group-text">
        <input aria-label="Checkbox for following text input" name="ingredient"
                th:value="${ingredient.name}" type="checkbox">
    </div>
    <input aria-label="Text input with checkbox" class="form-control" disabled
            th:value="${ingredient.name + '     ' + ingredient.price + 'Rs.'}"
            type="text">
</div>

assume "recipes" as model attribute here, which was injected to modelMap inside the controller.

when bean validation fails, below line exectutes.

if (errors.hasErrors()) return "selectItem";

and selectItem template is re-rendered, but whatever model attributes I have set inside previous controller vanishes.

I have solved this using a @ModelAttribute method inside the same controller to set model attributes for every HTTP requests for the specific controller(until it is not in controllerAdvice for global effect).

I am being confused if I am on right way || is there any elegant way to achieve this.

Setting Model attribute for every request is kind of overhead, when I want them to be available for handful of request mappings.

1 Answers

When you say:

selectItem template is re-rendered, but whatever model attributes I have set inside previous controller vanishes.

You mean that when the page reloads due to validation errors, your model attributes are no longer existing and Thymeleaf probably returns an error, because it cannot find them, correct?

If this is the case, then you have to manually prepare the same model attributes within the if statement (i.e. adding them to your MapModel):

if (errors.hasErrors()) {
 map.addAttribute("recipes", recipes);
 return "selectItem";
}

Alternatively, if you need this model attribute also on other pages in your controller, you can reduce code duplication by declaring a method with the ModelAttribute annotation, which will add this attribute to all models in your controller:

@ModelAttribute("recipes")
public Recipes loadRecipes() {
    // get list of Recipes
    return list;
}
Related