Reputation: 12026
In my Header HTML I display a UL/LI Menu where the visiblity of one of the LI items depends on a Service method call.
I tried this:
HomeController
@Controller
public class HomeController {
private static final Logger log = LogManager.getLogger(HomeController.class);
@Autowired
private EtdService etdService;
@GetMapping("/home")
public String home(Model model) throws EtdException {
model.addAttribute("tierTemplate", etdService.getTierTemplate());
// Also tried this explicitly
model.addAttribute("etdService", etdService);
return "home";
}
}
Service Interface (EtdService)
public interface EtdService {
boolean isChangeUserAllowed();
}
Service Implementation (EtdServiceImpl)
@Component
public class EtdServiceImpl implements EtdService {
@Override
public boolean isChangeUserAllowed() {
System.out.println("Got here");
return false;
}
}
HTML:
<li th:if="${@etdService.isChangeUserAllowed()}" class="nav-item dropdown" id="changeUserPanel" role="presentation">
<!-- ... Definition of this LI -- note can't put a new DIV in a UL list ... -->
</li>
Error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'etdService' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:772) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1221) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
Upvotes: 3
Views: 1855
Reputation: 12026
In addition to the answer by bphilipnyc (set the direct value into the model),
model.addAttribute("isChangeUserAllowed", etdService.isChangeUserAllowed());
If you need to globalize common Model Attributes without re-adding every time, a solution is a @ControllerAdvice
class with a @ModelAttribute
, e.g.
/**
* This class is used to globalize common Model Attributes without re-adding every time
* The approach is to mark it as @ControllerAdvice to make it apply to every Controller method,
* and implement a @ModelAttribute Model-Adder to append to the model on every Controller method.
*/
// Makes the methods of this class apply to all Controller Request methods
@ControllerAdvice
public class GlobalController {
@Autowired
MyService myService;
@ModelAttribute // A Model Attribute Adder method
public void setGlobalModelAttributes(HttpServletRequest request, Model model) {
model.addAttribute("isChangeUserAllowed", myService.isChangeUserAllowed());
model.addAttribute("currentUserFullName", myService.getCurrentUserFullName());
}
}
Some more examples
https://stackoverflow.com/a/33879102/1005607
https://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation
Upvotes: 3
Reputation: 9155
You are referencing an instance method in Thymeleaf. Here are two options:
1) Reference it by adding the value of the boolean to the model:
@GetMapping("/home")
public String home(Model model) throws EtdException {
//...
model.addAttribute("isChangeUserAllowed", etdService.isChangeUserAllowed());
return "home";
}
And in your HTML: th:if="${isChangeUserAllowed}"
To avoid NPEs, you can alternatively use #bools.isTrue(isChangeUserAllowed)
or the appropriate method in the bools
utility.
This is the preferred way and the path that the Thymeleaf documentation takes. A clear benefit is that the front-end is now not tied to the service.
2) Reference it statically instead (not recommended):
Error trying call method from view Thymeleaf Spring
Aside: the recommended way is to use constructor injection instead of autowiring.
Upvotes: 2