Frameworks
Spring Boot
Use WDS in a Spring Boot app with Thymeleaf templates.
Spring Boot renders HTML on the server, so it uses the ready-made wds.bundle.js: no Node.js in the project, no import map and no CDN. The component pages have no Spring Boot tab; use the code from their HTML tab.
Installation#
Copy the static files#
Put the bundle and the tokens in static, where Spring Boot serves them from.
tree
src/main/resources/
├── static/wds/
│ ├── wds.bundle.js <- @wds/core/dist/wds.bundle.js
│ └── tokens.css <- @wds/tokens/src/tokens.css
└── templates/
└── signup.htmlbash
# from a folder where @wds/core and @wds/tokens are installed
cp node_modules/@wds/core/dist/wds.bundle.js node_modules/@wds/tokens/src/tokens.css \
my-app/src/main/resources/static/wds/Add them to the template#
templates/signup.html
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" th:href="@{/wds/tokens.css}" />
<script type="module" th:src="@{/wds/wds.bundle.js}"></script>
</head>Forms and validation#
th:fieldworks only on native fields; forwds-*usenamewithth:valueorth:checked.- An error from
BindingResult:th:invalidonwds-fieldandth:errorsinwds-field-error. th:actionadds the_csrftoken when Spring Security is on.- A reset button goes back to the values rendered by the server.
templates/signup.html
<form method="post" th:action="@{/signup}" th:object="${signupForm}">
<!-- th:field works only on native fields: use name + th:value instead -->
<wds-field th:invalid="${#fields.hasErrors('email')} ? '' : null">
<wds-field-label>Email</wds-field-label>
<wds-input type="email" name="email" th:value="*{email}" required></wds-input>
<wds-field-error th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></wds-field-error>
</wds-field>
<wds-radio-group name="plan" th:value="*{plan}">
<wds-radio value="free">Free</wds-radio>
<wds-radio value="pro">Pro</wds-radio>
</wds-radio-group>
<!-- an unchecked checkbox sends nothing: _newsletter tells Spring to set false -->
<wds-checkbox name="newsletter" value="true" th:checked="*{newsletter}">Newsletter</wds-checkbox>
<input type="hidden" name="_newsletter" value="on" />
<wds-button type="submit">Create account</wds-button>
</form>SignupController.java
public class SignupForm {
@NotBlank @Email
private String email;
private String plan = "free";
private boolean newsletter;
// getters and setters
}
@Controller
public class SignupController {
@GetMapping("/signup")
public String form(Model model) {
model.addAttribute("signupForm", new SignupForm());
return "signup";
}
@PostMapping("/signup")
public String submit(@Valid SignupForm signupForm, BindingResult result) {
if (result.hasErrors()) {
return "signup"; // errors go to wds-field-error, the field gets invalid
}
return "redirect:/welcome";
}
}