Modern frontends with htmx Use htmx with Spring Boot and Thymeleaf to build dynamic and interactive web applications (Wim Deblauwe) (z-library.sk, 1lib.sk, z-lib.sk)
Author: Wim Deblauwe
Java
Imagine creating dynamic, interactive web applications with minimal JavaScript. That’s the revolutionary promise of htmx, a technology that redefines frontend development. This book is your gateway to mastering htmx alongside Java, Spring Boot, and Thymeleaf, transforming the way you build web interfaces.
📄 File Format:
PDF
💾 File Size:
13.6 MB
5
Views
0
Downloads
0.00
Total Donations
📄 Text Preview (First 20 pages)
ℹ️
Registered users can read the full content for free
Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.
📄 Page
1
(This page has no text content)
📄 Page
2
Modern frontends with htmx Use htmx with Spring Boot and Thymeleaf to build dynamic and interactive web applications Wim Deblauwe Version 1.0.0, 2023-12-03
📄 Page
3
Table of Contents Modern frontends with htmx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Source code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1. Technologies used in the book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.1. htmx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.2. Spring Framework. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.3. Spring Boot. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.4. Thymeleaf. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.5. Alpine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.6. Tailwind CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2. Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1. Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1.1. macOS/Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1.2. Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.2. ttcli. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.2.1. What is it? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.2.2. Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.2.3. Project generation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2.4. Run the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.3. IntelliJ IDEA plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.4. Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3. Starting with htmx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 3.1. Hello world example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 3.2. Triggers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.2.1. Trigger modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.2.2. Trigger filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.2.3. Special events. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 3.2.4. Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 3.3. Targets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.4. Swapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.5. HTTP verbs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.6. Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 4. Request and response headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 4.1. Request headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 4.2. Response headers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.3. Htmx-spring-boot library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 4.4. Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 5. Project 1: TodoMVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 5.1. Initial implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 5.2. Boost the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 5.3. Fine-grained htmx implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 5.3.1. Add a new todo item. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 5.3.2. Update number of items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
📄 Page
4
5.3.3. Mark item as completed. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 5.3.4. Delete item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 5.4. Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 6. Out of Band Swaps. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 6.1. General principles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 6.2. Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 6.2.1. Project generation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 6.2.2. Domain model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 6.2.3. UI setup. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 6.2.4. Input of time registration durations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 6.2.5. Day totals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 6.3. Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 7. Client-side scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 7.1. Vanilla JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 7.1.1. Project setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 7.1.2. Numbers Api . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 7.1.3. Web UI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 7.1.4. Progress indicator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 7.1.5. Error handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 7.2. AlpineJS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 7.2.1. Project setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 7.2.2. Domain model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 7.2.3. Inline editing of issue summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 7.2.4. Using drag and drop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 7.3. Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 8. Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 8.1. Htmx and security. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 8.2. Bookmarks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 8.2.1. Initialize project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 8.2.2. Add Spring Security. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 8.3. Classic Thymeleaf setup. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 8.4. Use htmx for adding a bookmark. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 8.5. Deleting a bookmark . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 8.5.1. Delete with hidden input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 8.5.2. Delete with meta tags. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 8.5.3. Delete with Thymeleaf inlining syntax for JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 8.6. Handle logout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 8.7. Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 9. Project 2: Contact application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 9.1. Setup project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 9.2. Add a contact. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 9.3. Search. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 9.4. View contact. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 9.5. Edit and delete a contact . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 9.6. Delete using htmx. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 9.7. Inline validation of duplicate email addresses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 9.7.1. Implement custom validator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 9.7.2. Trigger validation while typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
📄 Page
5
9.7.3. Improve the user experience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 9.7.4. Use hx-validate to avoid unnecessary requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 9.8. Pagination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 9.8.1. Generate contacts using Datafaker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 9.8.2. Manual pagination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 9.8.3. Click to load . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 9.8.4. Infinite scroll. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 9.9. Active search . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 9.9.1. Search pagination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 9.9.2. Search on type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 9.10. Delete row from list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 9.10.1. Fix the delete button redirect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 9.11. Archive list of contacts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 9.11.1. Archiver. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 9.11.2. Create an archive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 9.11.3. Download link . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 9.12. Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 10. Web components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 10.1. What are web components? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 10.2. Integrating Shoelace. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 10.3. GitHub Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 10.3.1. GitHub API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 10.3.2. Make it lazy. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 10.3.3. Add repository releases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 10.3.4. Show release notes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 10.4. Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232 11. Server-sent events & websockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 11.1. Server-sent events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 11.1.1. What are Server-sent events? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 11.1.2. Using the htmx sse extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 11.2. Websockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 11.2.1. What are websockets? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 11.2.2. Using the htmx ws extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 11.3. Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 12. Closing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Appendix A: Change log. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
📄 Page
6
Modern frontends with htmx © 2023 Wim Deblauwe. All rights reserved. Version 1.0.0. Published by Wim Deblauwe (wim.deblauwe@gmail.com) No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise except as permitted under Sections 107 or 108 of the 1976 United States Copyright Act, without the prior written permission of the publisher. While every precaution has been taken in the preparation of this book, the publisher and author assume no responsibility for errors and omissions, or for any damage resulting from the use of the information contained herein. The book solely reflects the author’s views. Cover Design: Jasmine Verhaeghe Modern frontends with htmx Modern frontends with htmx | 1
📄 Page
7
Foreword In my early days of professional programming, web application development generally followed a simple pattern: you pick a server-side technology, primarily according to your preference of programming language, development environment and complexity. Within each of those available tech stacks, a rough dozen of web frameworks existed that offered some flavor of the Model View Controller (MVC) pattern Those in turn supported various templating languages to enrich HTML documents with dynamic elements to be composed with the data residing on the server to produce a response. A consequence of that approach was that every user interaction with the browser required a full server round trip, rendering the full page again. Enter the Web 2.0 era. Web applications become much more dynamic by using AJAX requests. JavaScript enters the scene and libraries like jQuery become ubiquitous tools to sprinkle interactive elements into websites. Over the next decade, what started as enhancing addition, turned into fully- fledged frontend frameworks that, to a large degree, replicate many features that are present in the server-side ones: routing, state management, view rendering. That increase in complexity is multiplied by the need for additional tooling to build and deploy those, now separate, frontend applications. Furthermore, the backend now usually specializes in producing APIs the frontend can use, primarily in the form of providing access to data conveniently. Of course, that kind of sophistication on either side requires specialized skills and leads to developers slowly diverging into different camps. Nowadays, it is difficult to find a company developing web applications that does not feature dedicated backend and frontend teams, each specializing in the development of their specific part of the application. Up to a point, at which Conway’s Law kicks in: even simple, form-based applications are often developed with a frontend backend split, simply because that is the way the organization is structured. What is interesting about that kind of development (pun intended), is that it happens while the agile movement becomes the primary approach to software development in general. Cross-functional, self- determined teams are supposed to deliver value to customers in the form of working software as quickly as possible. Splitting up our development teams alongside technical boundaries does not really seem to help with that. Especially if that means that neither of the two can actually ship a feature on their own. During all that time, Spring Framework has been a ubiquitous player in the Java world to help developers build — not only — web applications. Unsurprisingly, it loosely followed the changes in approaches that I just described: primarily featuring Struts in its early days, different flavors of an own MVC framework supporting view technologies like JSP, Freemarker and ultimately Thymeleaf. The shift towards backend applications primarily providing data to frontends shifted the focus to JSON-based HTTP APIs, with bits of hypermedia elements in those for the more ambitious crowd. Building server-side rendered applications did not seem that appealing. That said, the trend of ever-growing complexity in web application development has produced a countermovement, culminating in projects like htmx, which this book is all about. With Taming Thymeleaf Wim already wrote the de-facto standard book on server-side rendered web application development with Spring. Unsurprisingly, htmx caught his interest, and he has been at the forefront of the community efforts to make it work easily within the Spring ecosystem. When I read the manuscript for this book for the first time, I could not have been more excited. It is a great, practical guide through htmx, Thymeleaf and Spring Boot and shows immediately applicable examples that each highlight a particular use case of the stack. I am pretty sure that this combination of technologies is going to play a very significant role in the next era of web application development with Java. And whom to better learn from about this than an expert on all three of those? Oliver Drotbohm Modern frontends with htmx 2 | Foreword
📄 Page
8
Acknowledgements I would first and foremost like to thank Carson Gross for creating htmx. It is only a little JavaScript library, on one hand; but allows so many developers to write rich interactive web applications in a simple way on the other hand. I also want to send a big thank-you to the people that created Asciidoctor (Especially Dan Allen), and to Alexander Schwartz for his amazing work on the IntelliJ Asciidoc plugin. It made writing this book extremely enjoyable. Further, I also want to thank my sister-in-law Jasmine Verhaeghe for the work on the book’s cover. I am really happy with how it looks. Finally, I want to thank Thomas Maxwell, Oliver Drotbohm, Frederik Hahne and Thomas Schuehly for reviewing the book. Their feedback has been invaluable for making this book the best it can be. Modern frontends with htmx Acknowledgements | 3
📄 Page
9
Introduction Imagine creating dynamic, interactive web applications with minimal JavaScript. That’s the revolutionary promise of htmx, a technology that redefines frontend development. This book is your gateway to mastering htmx alongside Java, Spring Boot, and Thymeleaf, transforming the way you build web interfaces. I can’t really remember when I learned about htmx for the first time, but I do know for sure it was via Twitter (Now called X). The account has some hilarious memes. But memes alone are not enough to grab my attention. What did grab my attention is the fact that htmx claims to drastically simplify frontend development. I love Spring Boot and Thymeleaf. However, those of you that have read my previous book Taming Thymeleaf, might have seen that it is not so easy to make something interactive. There was lots of JavaScript involved to allow editing the players of a team using UI patterns that users currently expect from a frontend application. Today, with htmx, I can discard most of that JavaScript for simpler implementations based on the idea of hypermedia. The fantastic thing about htmx that it makes modern UI patterns like lazy loading, endless scroll, inline editing, feedback-as-you-type, … real easy to implement. What’s equally great is the minimal learning curve involved. Htmx just continues where HTML got stuck in 1995. It allows issuing a server request from any element in your HTML. After all, why should only <a> and <form> be allowed to issue request? This book focuses on htmx combined with Java, Spring Boot, and Thymeleaf. However, it’s adaptable to various backend technologies. Htmx works equally well with Python/Django, PHP/Laravel, .NET/Blazor, … When using htmx, you need a backend that can return fragments like we have with Thymeleaf. This allows for precise HTML updates to update the page dynamically without page reloads. Throughout the book, I’ve included diverse examples. They’re designed not just to inform, but also to inspire. Let them be the spark for your own creative and technological journey. Enjoy the book, we are so back! Modern frontends with htmx 4 | Introduction
📄 Page
10
Source code The source code of the book can be found on GitHub at https://github.com/wimdeblauwe/modern- frontends-with-htmx-sources There is a directory per chapter with how the code is supposed to look by the end of each chapter. Modern frontends with htmx Source code | 5
📄 Page
11
Chapter 1. Technologies used in the book This book uses a few libraries and frameworks throughout. Some chapters use something extra which will be explained at that time. Here, we list the things that will be used constantly throughout the book. 1.1. htmx htmx is the core technology that this book will use to build our modern frontends. It is a JavaScript library that enhances HTML through the use of attributes on its elements. From the website: htmx gives you access to AJAX, CSS Transitions, WebSockets and Server Sent Events directly in HTML, using attributes, so you can build modern user interfaces with the simplicity and power of hypertext The core idea of htmx is that you swap HTML snippets on the page in the browser with new HTML snippets coming from the server. Those can come as a response to a request, or can be pushed from the server in case of Server-Sent Events or websockets. Htmx is backend framework-agnostic. You can use it with PHP, Python, .NET, Java, … Really, anything that can return HTML from the server will work with it. See the htmx website for more information. 1.2. Spring Framework Spring Boot is based upon the Spring Framework, which is at its core a dependency-injection container. Spring makes it easy to define everything in your application as loosely coupled components which Spring will tie together at run time. Spring also has a programming model that allows you to make abstractions from specific deployment environments. One of the key things you need to understand is that Spring is based on the concept of "beans" or "components", which are basically singletons without the drawbacks of the traditional singleton pattern. With dependency injection, each component just declares the collaborators it needs, and Spring provides them at run time. The biggest advantage is that you can inject different instances for different deployment scenarios of your application (e.g., staging versus production versus unit tests). The Spring portfolio includes a lot of subprojects ranging from database access over security to cloud services. The specific subprojects used in this book are: Spring Web MVC Spring Web MVC is Spring’s web framework built on the Servlet API. Spring Security Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications. You can learn more about the core Spring Framework at Spring Framework Documentation. Modern frontends with htmx 6 | Chapter 1. Technologies used in the book
📄 Page
12
1.3. Spring Boot The Spring Boot website explains itself succinctly: Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run". We take an opinionated view of the Spring platform and third-party libraries, so you can get started with minimum fuss. Most Spring Boot applications need very little Spring configuration. With Spring Boot, you get up and running with your Spring application in no time, without the need to deploy to a container like Tomcat or Jetty. You can just run the application right from your IDE. Spring Boot also ensures that you get a list of versions of libraries inside and outside the Spring portfolio that are guaranteed to work together without problems. You can learn more about Spring Boot from the excellent Spring Boot Reference Documentation. 1.4. Thymeleaf Thymeleaf is a server-side Java template engine that uses natural templates to generate HTML pages. Natural templates are HTML templates that can correctly be displayed in browsers and work as static prototypes. Learn more about Thymeleaf at the Thymeleaf Documentation. This book assumes you have a basic understanding of Thymeleaf. If you are not familiar with it, consider reading Taming Thymeleaf first. It shows how to build a full stack web application with Thymeleaf step-by-step. Htmx is not tied to Thymeleaf. It is certainly possible to use other templating engines that Spring supports such as Apache Freemarker or JTE. 1.5. Alpine In some cases, we will want to have some client-side interactivity. We can use vanilla JavaScript for this, but in some cases, it will be easier to use the Alpine library. Like htmx, it uses attributes on the HTML to define the behavior. It shares what is called the Locality of Behaviour principle: The behaviour of a unit of code should be as obvious as possible by looking only at that unit of code See the Alpine website for more info. 1.6. Tailwind CSS Tailwind CSS is a utility-first CSS framework. If you want a good introduction, checkout the very informative screencasts on the website. In a nutshell, the goal of Tailwind is that you need almost no custom CSS. You apply ready-made classes to your HTML. Modern frontends with htmx Chapter 1. Technologies used in the book | 7
📄 Page
13
It can be a bit overwhelming at the start to see many classes on your HTML when you use Tailwind CSS. But give it the benefit of the doubt. Once you have used a bit, you will probably quite like it. Modern frontends with htmx 8 | Chapter 1. Technologies used in the book
📄 Page
14
Chapter 2. Getting started 2.1. Prerequisites To be able to create a Spring Boot application, we need to install Java and Maven as a build tool. We will use Java 17, which is the minimal version that Spring Boot 3 needs. You can also use Java 21 if you like. 2.1.1. macOS/Linux Use SDKMAN! to install Java and Maven. 1. Follow the SDKMAN! installation instructions at https://sdkman.io/install: curl -s "https://get.sdkman.io" | bash 2. Install Java: sdk install java 17.0.6-tem Use sdk list java to see a list of all possible Java versions that can be installed. 3. Install Maven: sdk install maven 3.8.7 4. Run mvn --version to see if both are configured correctly. The output should look similar to this: wdb@Wims-MacBook-Pro ~ % mvn --version Apache Maven 3.8.7 (b89d5959fcde851dcb1c8946a785a163f14e1e29) Maven home: /Users/wdb/.sdkman/candidates/maven/current Java version: 17.0.6, vendor: Eclipse Adoptium, runtime: /Users/wdb/.sdkman/candidates/java/17.0.6-tem Default locale: en_BE, platform encoding: UTF-8 OS name: "mac os x", version: "12.6.3", arch: "x86_64", family: "mac" 2.1.2. Windows Use Chocolatey to install Java and Maven. 1. Follow the Chocolatey installation instructions at https://chocolatey.org/install. Modern frontends with htmx Chapter 2. Getting started | 9
📄 Page
15
2. Install Java choco install temurin 3. Install Maven choco install maven 4. Run mvn -v to see if both are configured correctly. The output should look similar to this: Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537) Maven home: C:\ProgramData\chocolatey\lib\maven\apache-maven-3.8.4 Java version: 17.0.1, vendor: Eclipse Adoptium, runtime: C:\Program Files\Eclipse Adoptium\jdk-17.0.1.12-hotspot Default locale: nl_BE, platform encoding: Cp1252 OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows" 2.2. ttcli 2.2.1. What is it? The easiest way to get started with Spring Boot is to create a project using Spring Initializr. This web application allows you to generate a Spring Boot project with the option of including all the dependencies you need. However, to quickly have a setup with live reload and support for htmx and Alpine, it is easier to use ttcli. This command line tool generates a Spring Boot with Thymeleaf project with the following things configured automatically: • Tailwind CSS compiler so that the proper CSS is created as we change our HTML. • Live reload so we can quickly check any changes visually in the browser. • Maven build calling npm so the frontend part of the application is properly built using a single Maven command. • Webjars dependencies for htmx and alpine (and optionally bootstrap if you prefer this over Tailwind CSS). 2.2.2. Installation A prerequisite is that you need to have npm installed for ttcli to work. For macOS and Linux, the easiest is using nvm to install node and npm. Windows users can use nvm-windows. Modern frontends with htmx 10 | Chapter 2. Getting started
📄 Page
16
Download the latest release from https://github.com/wimdeblauwe/ttcli/releases. If you are on macOS, you can install it using Homebrew: brew install wimdeblauwe/homebrew-ttcli/ttcli For Windows, you can use Chocolatey: choco install ttcli 2.2.3. Project generation Open a terminal and run ttcli init. Answer the questions like this: • Group: com.modernfrontendshtmx • Artifact: modern-frontends-htmx • Project Name: Modern Frontends Htmx • Spring Boot version: 3.1.4 • Live reload: NPM based with Tailwind CSS • Web dependencies: htmx and Alpine.js We will not be using htmx or Alpine for this little project, but I just add them here as an example. You can also just generate the project without any web dependencies for now. After a few minutes (Depending on your internet speed, as it needs to download quite a few things), the project is generated: Modern frontends with htmx Chapter 2. Getting started | 11
📄 Page
17
Figure 1. Example run of the ttcli tool The generated project has a file structure like this: ├── HELP.md ├── mvnw ├── mvnw.cmd ├── package-lock.json ├── package.json ├── pom.xml ├── postcss.config.js ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── modernfrontendshtmx │ │ │ └── modernfrontendshtmx │ │ │ ├── HomeController.java │ │ │ └── ModernFrontendsHtmxApplication.java │ │ └── resources │ │ ├── application-local.properties │ │ ├── application.properties │ │ ├── static Modern frontends with htmx 12 | Chapter 2. Getting started
📄 Page
18
│ │ │ └── css │ │ │ └── application.css │ │ └── templates │ │ ├── index.html │ │ └── layout │ │ └── main.html │ └── test │ └── java │ └── com │ └── modernfrontendshtmx │ └── modernfrontendshtmx │ └── ModernFrontendsHtmxApplicationTests.java └── tailwind.config.js The most important things to know: • package.json contains the npm scripts for building the client side of things. The 3 most important scripts are build, build-prod and watch. ◦ build: builds the HTML, Javascript and CSS and copies it to the target/classes directory where Spring Boot expects them. ◦ build-prod: builds everything just as build but will also minify the CSS and JS. For example, run npm run build-prod and compare the generated CSS with running npm run build to see the minification in action. ◦ watch: Watches the HTML, Javascript and CSS source files for changes and automatically runs build when they changed. • pom.xml contains the Maven configuation. ◦ It is configured so that running mvn clean verify will run the appropriate npm script as well, so the application is fully built by just using Maven. ◦ It has exclusions for html, css, js and svg files as we will rely on the npm scripts to copy those to the target directory. ◦ To build for production, use the release Maven profile: mvn verify -Prelease • tailwind.config.js and postcss.config.js contain the configuration for Tailwind CSS and PostCSS respectively. • HomeController is a Spring MVC controller that serves the index.html Thymeleaf template when accessing the root of the application through the browser (By default: http://localhost:8080) • src/main/resources/static/css/application.css has the Tailwind standard CSS file which only has 3 lines: @tailwind base; @tailwind components; @tailwind utilities; Those lines with the Tailwind CSS compiler will generate all the CSS you need. Modern frontends with htmx Chapter 2. Getting started | 13
📄 Page
19
The ttcli tool also generates an index.html and layout/main.html which are 2 starter Thymeleaf templates. Let’s add a bit of Tailwind CSS styling to the index.html. This is how it looks by default: src/main/resources/templates/index.html <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/main}"> <body> <div layout:fragment="content"> <!-- Add content here --> <div>Welcome to your Spring Boot with Thymeleaf project!</div> <div>See <code>HELP.md</code> for instructions on how to get started.</div> </div> </body> </html> Let’s change it to: <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/main}"> <body> <div layout:fragment="content" class="m-4"> ① <!-- Add content here --> <div class="text-xl">Welcome to your Spring Boot with Thymeleaf project!</div> ② <div>See <code class="bg-yellow-500 px-2">HELP.md</code> for instructions on how to get started.</div> ③ </div> </body> </html> ① Set a margin on the content. ② Increase the text font size. ③ Use a yellow background and some horizontal padding. After these changes, we can now run the application. Modern frontends with htmx 14 | Chapter 2. Getting started
📄 Page
20
2.2.4. Run the application Start the Spring Boot application using the local profile. If you use IntelliJ IDEA, you can configure this in the run configuration: Figure 2. IntelliJ run configuration dialog This is only available in IntelliJ IDEA Ultimate. I would strongly suggest getting that version since it has support for Thymeleaf and JavaScript as well. However, if you use the community edition, you can add -Dspring.profiles.active=local to the VM options to activate the local profile. If you want to run from the command line, you would need to create a jar using mvn verify and after that run the following command: java -Dspring.profiles.active=local -jar target/modern- frontends-htmx-0.0.1-SNAPSHOT.jar With the Java application running, open a terminal and run the following command: npm run build && npm run watch This will automatically open your default browser at http://localhost:3000. It should look like this: Modern frontends with htmx Chapter 2. Getting started | 15
The above is a preview of the first 20 pages. Register to read the complete e-book.